diff options
Diffstat (limited to 'shell/math.c')
-rw-r--r-- | shell/math.c | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/shell/math.c b/shell/math.c index e5447e767..d9986335a 100644 --- a/shell/math.c +++ b/shell/math.c | |||
@@ -613,7 +613,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) | |||
613 | const char *start_expr = expr = skip_whitespace(expr); | 613 | const char *start_expr = expr = skip_whitespace(expr); |
614 | 614 | ||
615 | { | 615 | { |
616 | unsigned expr_len = strlen(expr) + 2; | 616 | unsigned expr_len = strlen(expr); |
617 | /* If LOTS of whitespace, do not blow up the estimation */ | 617 | /* If LOTS of whitespace, do not blow up the estimation */ |
618 | const char *p = expr; | 618 | const char *p = expr; |
619 | while (*p) { | 619 | while (*p) { |
@@ -625,14 +625,21 @@ evaluate_string(arith_state_t *math_state, const char *expr) | |||
625 | p++; | 625 | p++; |
626 | } | 626 | } |
627 | } | 627 | } |
628 | /* There can be no more than expr_len/2 | 628 | dbg("expr:'%s' expr_len:%u", expr, expr_len); |
629 | /* expr_len deep opstack is needed. Think "------------7". | ||
630 | * Only "?" operator temporarily needs two opstack slots | ||
631 | * (IOW: more than one slot), but its second slot (LPAREN) | ||
632 | * is popped off when ":" is reached. | ||
633 | */ | ||
634 | opstackptr = opstack = alloca(expr_len * sizeof(opstack[0])); | ||
635 | /* There can be no more than (expr_len/2 + 1) | ||
629 | * integers/names in any given correct or incorrect expression. | 636 | * integers/names in any given correct or incorrect expression. |
630 | * (modulo "09v09v09v09v09v" case, | 637 | * (modulo "09", "0v" cases where 2 chars are 2 ints/names, |
631 | * but we have code to detect that early) | 638 | * but we have code to detect that early) |
632 | */ | 639 | */ |
633 | dbg("expr:'%s' expr_len:%u", expr, expr_len); | 640 | expr_len = (expr_len / 2) |
634 | numstackptr = numstack = alloca((expr_len / 2) * sizeof(numstack[0])); | 641 | + 1 /* "1+2" has two nums, 2 = len/2+1, NOT len/2 */; |
635 | opstackptr = opstack = alloca(expr_len * sizeof(opstack[0])); | 642 | numstackptr = numstack = alloca(expr_len * sizeof(numstack[0])); |
636 | } | 643 | } |
637 | 644 | ||
638 | /* Start with a left paren */ | 645 | /* Start with a left paren */ |
@@ -714,8 +721,9 @@ evaluate_string(arith_state_t *math_state, const char *expr) | |||
714 | dbg("[%d] val:%lld", (int)(numstackptr - numstack), numstackptr->val); | 721 | dbg("[%d] val:%lld", (int)(numstackptr - numstack), numstackptr->val); |
715 | /* A number can't be followed by another number, or a variable name. | 722 | /* A number can't be followed by another number, or a variable name. |
716 | * We'd catch this later anyway, but this would require numstack[] | 723 | * We'd catch this later anyway, but this would require numstack[] |
717 | * to be twice as deep to handle strings where _every_ char is | 724 | * to be ~twice as deep to handle strings where _every_ char is |
718 | * a new number or name. Example: 09v09v09v09v09v09v09v09v09v | 725 | * a new number or name. |
726 | * Examples: "09" is two numbers, "0v" is number and name. | ||
719 | */ | 727 | */ |
720 | if (isalnum(*expr) || *expr == '_') | 728 | if (isalnum(*expr) || *expr == '_') |
721 | goto syntax_err; | 729 | goto syntax_err; |