diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2023-07-02 19:32:12 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2023-07-02 19:32:12 +0200 |
commit | cc9543fed1f916f62a63cfbe9eaefba3df8e22cb (patch) | |
tree | ca45333b5d738d2ccad7fb2ef65a3b8f423b4b6f | |
parent | 045924ed7d3c887cce1c6a22a0b4e0b692719154 (diff) | |
download | busybox-w32-cc9543fed1f916f62a63cfbe9eaefba3df8e22cb.tar.gz busybox-w32-cc9543fed1f916f62a63cfbe9eaefba3df8e22cb.tar.bz2 busybox-w32-cc9543fed1f916f62a63cfbe9eaefba3df8e22cb.zip |
shell/math: avoid $((3**999999999999999999)) to take years
function old new delta
arith_apply 991 1030 +39
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/math.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/shell/math.c b/shell/math.c index b06d1ae3c..e90a38f05 100644 --- a/shell/math.c +++ b/shell/math.c | |||
@@ -155,7 +155,7 @@ typedef unsigned char operator; | |||
155 | #define PREC_ASSIGN2 3 | 155 | #define PREC_ASSIGN2 3 |
156 | #define TOK_MUL_ASSIGN tok_decl(3,0) | 156 | #define TOK_MUL_ASSIGN tok_decl(3,0) |
157 | /* "/" and "/=" ops have the same id bits */ | 157 | /* "/" and "/=" ops have the same id bits */ |
158 | #define DIV_ID1 1 | 158 | #define DIV_ID1 1 |
159 | #define TOK_DIV_ASSIGN tok_decl(3,DIV_ID1) | 159 | #define TOK_DIV_ASSIGN tok_decl(3,DIV_ID1) |
160 | #define TOK_REM_ASSIGN tok_decl(3,2) | 160 | #define TOK_REM_ASSIGN tok_decl(3,2) |
161 | 161 | ||
@@ -422,8 +422,19 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ | |||
422 | if (right_side_val < 0) | 422 | if (right_side_val < 0) |
423 | return "exponent less than 0"; | 423 | return "exponent less than 0"; |
424 | c = 1; | 424 | c = 1; |
425 | while (--right_side_val >= 0) | 425 | while (right_side_val != 0) { |
426 | if ((right_side_val & 1) == 0) { | ||
427 | /* this if() block is not necessary for correctness, | ||
428 | * but otherwise echo $((3**999999999999999999)) | ||
429 | * takes a VERY LONG time | ||
430 | * (and it's not interruptible by ^C) | ||
431 | */ | ||
432 | rez *= rez; | ||
433 | right_side_val >>= 1; | ||
434 | } | ||
426 | c *= rez; | 435 | c *= rez; |
436 | right_side_val--; | ||
437 | } | ||
427 | rez = c; | 438 | rez = c; |
428 | } | 439 | } |
429 | else /*if (op == TOK_DIV || op == TOK_DIV_ASSIGN | 440 | else /*if (op == TOK_DIV || op == TOK_DIV_ASSIGN |
@@ -550,7 +561,7 @@ static arith_t parse_with_base(const char *nptr, char **endptr, unsigned base) | |||
550 | /* current char is one of :;<=>?@A..Z[\]^_`a..z */ | 561 | /* current char is one of :;<=>?@A..Z[\]^_`a..z */ |
551 | 562 | ||
552 | /* in bases up to 36, case does not matter for a-z, | 563 | /* in bases up to 36, case does not matter for a-z, |
553 | * map A..Z and a..z to 10..35: */ | 564 | * map @A..Z and `a..z to 9..35: */ |
554 | digit = (unsigned)(*nptr | 0x20) - ('a' - 10); | 565 | digit = (unsigned)(*nptr | 0x20) - ('a' - 10); |
555 | if (base > 36 && *nptr <= '_') { | 566 | if (base > 36 && *nptr <= '_') { |
556 | /* base > 36: A-Z,@,_ are 36-61,62,63 */ | 567 | /* base > 36: A-Z,@,_ are 36-61,62,63 */ |