diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2023-06-12 17:48:47 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2023-06-12 17:48:47 +0200 |
commit | d417193cf37ca1005830d7e16f5fa7e1d8a44209 (patch) | |
tree | 5516db4bcc998f4c850e37697dd7e5ede9f6606c | |
parent | bab8828b0dad1d51d6b34e38249f0641ca64b1e9 (diff) | |
download | busybox-w32-d417193cf37ca1005830d7e16f5fa7e1d8a44209.tar.gz busybox-w32-d417193cf37ca1005830d7e16f5fa7e1d8a44209.tar.bz2 busybox-w32-d417193cf37ca1005830d7e16f5fa7e1d8a44209.zip |
shell: avoid segfault on ${0::0/0~09J}. Closes 15216
function old new delta
evaluate_string 1011 1053 +42
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/math.c | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/shell/math.c b/shell/math.c index 76d22c9bd..727c29467 100644 --- a/shell/math.c +++ b/shell/math.c | |||
@@ -577,6 +577,28 @@ static arith_t strto_arith_t(const char *nptr, char **endptr) | |||
577 | # endif | 577 | # endif |
578 | #endif | 578 | #endif |
579 | 579 | ||
580 | //TODO: much better estimation than expr_len/2? Such as: | ||
581 | //static unsigned estimate_nums_and_names(const char *expr) | ||
582 | //{ | ||
583 | // unsigned count = 0; | ||
584 | // while (*(expr = skip_whitespace(expr)) != '\0') { | ||
585 | // const char *p; | ||
586 | // if (isdigit(*expr)) { | ||
587 | // while (isdigit(*++expr)) | ||
588 | // continue; | ||
589 | // count++; | ||
590 | // continue; | ||
591 | // } | ||
592 | // p = endofname(expr); | ||
593 | // if (p != expr) { | ||
594 | // expr = p; | ||
595 | // count++; | ||
596 | // continue; | ||
597 | // } | ||
598 | // } | ||
599 | // return count; | ||
600 | //} | ||
601 | |||
580 | static arith_t | 602 | static arith_t |
581 | evaluate_string(arith_state_t *math_state, const char *expr) | 603 | evaluate_string(arith_state_t *math_state, const char *expr) |
582 | { | 604 | { |
@@ -584,10 +606,12 @@ evaluate_string(arith_state_t *math_state, const char *expr) | |||
584 | const char *errmsg; | 606 | const char *errmsg; |
585 | const char *start_expr = expr = skip_whitespace(expr); | 607 | const char *start_expr = expr = skip_whitespace(expr); |
586 | unsigned expr_len = strlen(expr) + 2; | 608 | unsigned expr_len = strlen(expr) + 2; |
587 | /* Stack of integers */ | 609 | /* Stack of integers/names */ |
588 | /* The proof that there can be no more than strlen(startbuf)/2+1 | 610 | /* There can be no more than strlen(startbuf)/2+1 |
589 | * integers in any given correct or incorrect expression | 611 | * integers/names in any given correct or incorrect expression. |
590 | * is left as an exercise to the reader. */ | 612 | * (modulo "09v09v09v09v09v" case, |
613 | * but we have code to detect that early) | ||
614 | */ | ||
591 | var_or_num_t *const numstack = alloca((expr_len / 2) * sizeof(numstack[0])); | 615 | var_or_num_t *const numstack = alloca((expr_len / 2) * sizeof(numstack[0])); |
592 | var_or_num_t *numstackptr = numstack; | 616 | var_or_num_t *numstackptr = numstack; |
593 | /* Stack of operator tokens */ | 617 | /* Stack of operator tokens */ |
@@ -652,6 +676,13 @@ evaluate_string(arith_state_t *math_state, const char *expr) | |||
652 | numstackptr->var = NULL; | 676 | numstackptr->var = NULL; |
653 | errno = 0; | 677 | errno = 0; |
654 | numstackptr->val = strto_arith_t(expr, (char**) &expr); | 678 | numstackptr->val = strto_arith_t(expr, (char**) &expr); |
679 | /* A number can't be followed by another number, or a variable name. | ||
680 | * We'd catch this later anyway, but this would require numstack[] | ||
681 | * to be twice as deep to handle strings where _every_ char is | ||
682 | * a new number or name. Example: 09v09v09v09v09v09v09v09v09v | ||
683 | */ | ||
684 | if (isalnum(*expr) || *expr == '_') | ||
685 | goto err; | ||
655 | //bb_error_msg("val:%lld", numstackptr->val); | 686 | //bb_error_msg("val:%lld", numstackptr->val); |
656 | if (errno) | 687 | if (errno) |
657 | numstackptr->val = 0; /* bash compat */ | 688 | numstackptr->val = 0; /* bash compat */ |