aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2023-06-12 17:48:47 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2023-06-12 17:48:47 +0200
commitd417193cf37ca1005830d7e16f5fa7e1d8a44209 (patch)
tree5516db4bcc998f4c850e37697dd7e5ede9f6606c
parentbab8828b0dad1d51d6b34e38249f0641ca64b1e9 (diff)
downloadbusybox-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.c39
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
580static arith_t 602static arith_t
581evaluate_string(arith_state_t *math_state, const char *expr) 603evaluate_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 */