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 /shell | |
| 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>
Diffstat (limited to 'shell')
| -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 */ |
