diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2023-07-02 17:58:20 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2023-07-02 17:58:20 +0200 |
commit | 045924ed7d3c887cce1c6a22a0b4e0b692719154 (patch) | |
tree | 62bcf0ddaa7f09205583e643709ee69828fc4354 | |
parent | 38f769ab4e5f6cd2ffab88300ddaddef3aac3345 (diff) | |
download | busybox-w32-045924ed7d3c887cce1c6a22a0b4e0b692719154.tar.gz busybox-w32-045924ed7d3c887cce1c6a22a0b4e0b692719154.tar.bz2 busybox-w32-045924ed7d3c887cce1c6a22a0b4e0b692719154.zip |
shell/math: do not accept $((36#@))
function old new delta
parse_with_base 170 174 +4
arith_apply 996 991 -5
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 4/-5) Total: -1 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/math.c | 38 |
1 files changed, 22 insertions, 16 deletions
diff --git a/shell/math.c b/shell/math.c index beb89d140..b06d1ae3c 100644 --- a/shell/math.c +++ b/shell/math.c | |||
@@ -128,7 +128,8 @@ typedef unsigned char operator; | |||
128 | * Consider * and / | 128 | * Consider * and / |
129 | */ | 129 | */ |
130 | #define tok_decl(prec,id) (((id)<<5) | (prec)) | 130 | #define tok_decl(prec,id) (((id)<<5) | (prec)) |
131 | #define PREC(op) ((op) & 0x1F) | 131 | #define ID_SHIFT 5 |
132 | #define PREC(op) ((op) & 0x1f) | ||
132 | 133 | ||
133 | #define PREC_LPAREN 0 | 134 | #define PREC_LPAREN 0 |
134 | #define TOK_LPAREN tok_decl(0,0) | 135 | #define TOK_LPAREN tok_decl(0,0) |
@@ -146,14 +147,16 @@ typedef unsigned char operator; | |||
146 | #define TOK_AND_ASSIGN tok_decl(2,1) | 147 | #define TOK_AND_ASSIGN tok_decl(2,1) |
147 | #define TOK_OR_ASSIGN tok_decl(2,2) | 148 | #define TOK_OR_ASSIGN tok_decl(2,2) |
148 | #define TOK_XOR_ASSIGN tok_decl(2,3) | 149 | #define TOK_XOR_ASSIGN tok_decl(2,3) |
149 | #define TOK_PLUS_ASSIGN tok_decl(2,4) | 150 | #define TOK_ADD_ASSIGN tok_decl(2,4) |
150 | #define TOK_MINUS_ASSIGN tok_decl(2,5) | 151 | #define TOK_SUB_ASSIGN tok_decl(2,5) |
151 | #define TOK_LSHIFT_ASSIGN tok_decl(2,6) | 152 | #define TOK_LSHIFT_ASSIGN tok_decl(2,6) |
152 | #define TOK_RSHIFT_ASSIGN tok_decl(2,7) | 153 | #define TOK_RSHIFT_ASSIGN tok_decl(2,7) |
153 | 154 | ||
154 | #define PREC_ASSIGN2 3 | 155 | #define PREC_ASSIGN2 3 |
155 | #define TOK_MUL_ASSIGN tok_decl(3,0) | 156 | #define TOK_MUL_ASSIGN tok_decl(3,0) |
156 | #define TOK_DIV_ASSIGN tok_decl(3,1) | 157 | /* "/" and "/=" ops have the same id bits */ |
158 | #define DIV_ID1 1 | ||
159 | #define TOK_DIV_ASSIGN tok_decl(3,DIV_ID1) | ||
157 | #define TOK_REM_ASSIGN tok_decl(3,2) | 160 | #define TOK_REM_ASSIGN tok_decl(3,2) |
158 | 161 | ||
159 | #define fix_assignment_prec(prec) do { prec -= (prec == 3); } while (0) | 162 | #define fix_assignment_prec(prec) do { prec -= (prec == 3); } while (0) |
@@ -198,7 +201,7 @@ typedef unsigned char operator; | |||
198 | #define TOK_SUB tok_decl(13,1) | 201 | #define TOK_SUB tok_decl(13,1) |
199 | 202 | ||
200 | #define TOK_MUL tok_decl(14,0) | 203 | #define TOK_MUL tok_decl(14,0) |
201 | #define TOK_DIV tok_decl(14,1) | 204 | #define TOK_DIV tok_decl(14,DIV_ID1) |
202 | #define TOK_REM tok_decl(14,2) | 205 | #define TOK_REM tok_decl(14,2) |
203 | 206 | ||
204 | /* Exponent is right associative */ | 207 | /* Exponent is right associative */ |
@@ -408,9 +411,9 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ | |||
408 | rez = (rez <= right_side_val); | 411 | rez = (rez <= right_side_val); |
409 | else if (op == TOK_MUL || op == TOK_MUL_ASSIGN) | 412 | else if (op == TOK_MUL || op == TOK_MUL_ASSIGN) |
410 | rez *= right_side_val; | 413 | rez *= right_side_val; |
411 | else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN) | 414 | else if (op == TOK_ADD || op == TOK_ADD_ASSIGN) |
412 | rez += right_side_val; | 415 | rez += right_side_val; |
413 | else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN) | 416 | else if (op == TOK_SUB || op == TOK_SUB_ASSIGN) |
414 | rez -= right_side_val; | 417 | rez -= right_side_val; |
415 | else if (op == TOK_ASSIGN || op == TOK_COMMA) | 418 | else if (op == TOK_ASSIGN || op == TOK_COMMA) |
416 | rez = right_side_val; | 419 | rez = right_side_val; |
@@ -439,11 +442,11 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ | |||
439 | * Make sure to at least not SEGV here: | 442 | * Make sure to at least not SEGV here: |
440 | */ | 443 | */ |
441 | if (right_side_val == -1 | 444 | if (right_side_val == -1 |
442 | && rez << 1 == 0 /* MAX_NEGATIVE_INT or 0 */ | 445 | && (rez << 1) == 0 /* MAX_NEGATIVE_INT or 0 */ |
443 | ) { | 446 | ) { |
444 | right_side_val = 1; | 447 | right_side_val = 1; |
445 | } | 448 | } |
446 | if (op == TOK_DIV || op == TOK_DIV_ASSIGN) | 449 | if (op & (DIV_ID1 << ID_SHIFT)) /* DIV or DIV_ASSIGN? */ |
447 | rez /= right_side_val; | 450 | rez /= right_side_val; |
448 | else | 451 | else |
449 | rez %= right_side_val; | 452 | rez %= right_side_val; |
@@ -505,8 +508,8 @@ static const char op_tokens[] ALIGN1 = { | |||
505 | '*','=', 0, TOK_MUL_ASSIGN, | 508 | '*','=', 0, TOK_MUL_ASSIGN, |
506 | '/','=', 0, TOK_DIV_ASSIGN, | 509 | '/','=', 0, TOK_DIV_ASSIGN, |
507 | '%','=', 0, TOK_REM_ASSIGN, | 510 | '%','=', 0, TOK_REM_ASSIGN, |
508 | '+','=', 0, TOK_PLUS_ASSIGN, | 511 | '+','=', 0, TOK_ADD_ASSIGN, |
509 | '-','=', 0, TOK_MINUS_ASSIGN, | 512 | '-','=', 0, TOK_SUB_ASSIGN, |
510 | '-','-', 0, TOK_POST_DEC, | 513 | '-','-', 0, TOK_POST_DEC, |
511 | '^','=', 0, TOK_XOR_ASSIGN, | 514 | '^','=', 0, TOK_XOR_ASSIGN, |
512 | '+','+', 0, TOK_POST_INC, | 515 | '+','+', 0, TOK_POST_INC, |
@@ -542,12 +545,15 @@ static arith_t parse_with_base(const char *nptr, char **endptr, unsigned base) | |||
542 | for (;;) { | 545 | for (;;) { |
543 | unsigned digit = (unsigned)*nptr - '0'; | 546 | unsigned digit = (unsigned)*nptr - '0'; |
544 | if (digit >= 10 /* not 0..9 */ | 547 | if (digit >= 10 /* not 0..9 */ |
545 | && digit <= 'z' - '0' /* needed to reject e.g. $((64#~)) */ | 548 | && digit <= 'z' - '0' /* reject e.g. $((64#~)) */ |
546 | ) { | 549 | ) { |
547 | /* in bases up to 36, case does not matter for a-z */ | 550 | /* current char is one of :;<=>?@A..Z[\]^_`a..z */ |
551 | |||
552 | /* in bases up to 36, case does not matter for a-z, | ||
553 | * map A..Z and a..z to 10..35: */ | ||
548 | digit = (unsigned)(*nptr | 0x20) - ('a' - 10); | 554 | digit = (unsigned)(*nptr | 0x20) - ('a' - 10); |
549 | if (base > 36 && *nptr <= '_') { | 555 | if (base > 36 && *nptr <= '_') { |
550 | /* otherwise, A-Z,@,_ are 36-61,62,63 */ | 556 | /* base > 36: A-Z,@,_ are 36-61,62,63 */ |
551 | if (*nptr == '_') | 557 | if (*nptr == '_') |
552 | digit = 63; | 558 | digit = 63; |
553 | else if (*nptr == '@') | 559 | else if (*nptr == '@') |
@@ -558,8 +564,8 @@ static arith_t parse_with_base(const char *nptr, char **endptr, unsigned base) | |||
558 | break; /* error: one of [\]^ */ | 564 | break; /* error: one of [\]^ */ |
559 | } | 565 | } |
560 | //bb_error_msg("ch:'%c'%d digit:%u", *nptr, *nptr, digit); | 566 | //bb_error_msg("ch:'%c'%d digit:%u", *nptr, *nptr, digit); |
561 | //if (digit < 10) - example where we need this? | 567 | if (digit < 10) /* reject e.g. $((36#@)) */ |
562 | // break; | 568 | break; |
563 | } | 569 | } |
564 | if (digit >= base) | 570 | if (digit >= base) |
565 | break; | 571 | break; |