|
| 1 | +From d417193cf37ca1005830d7e16f5fa7e1d8a44209 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Denys Vlasenko < [email protected]> |
| 3 | +Date: Mon, 12 Jun 2023 17:48:47 +0200 |
| 4 | +Subject: [PATCH] shell: avoid segfault on ${0::0/0~09J}. Closes 15216 |
| 5 | + |
| 6 | +function old new delta |
| 7 | +evaluate_string 1011 1053 +42 |
| 8 | + |
| 9 | +Signed-off-by: Denys Vlasenko < [email protected]> |
| 10 | + |
| 11 | +Upstream Patch Reference : https://git.busybox.net/busybox/commit/?id=d417193cf37ca1005830d7e16f5fa7e1d8a44209 |
| 12 | +Signed-off-by: Kanishk Bansal < [email protected]> |
| 13 | +--- |
| 14 | + shell/math.c | 39 +++++++++++++++++++++++++++++++++++---- |
| 15 | + 1 file changed, 35 insertions(+), 4 deletions(-) |
| 16 | + |
| 17 | +diff --git a/shell/math.c b/shell/math.c |
| 18 | +index 76d22c9bd5..727c294674 100644 |
| 19 | +--- a/shell/math.c |
| 20 | ++++ b/shell/math.c |
| 21 | +@@ -577,6 +577,28 @@ static arith_t strto_arith_t(const char *nptr, char **endptr) |
| 22 | + # endif |
| 23 | + #endif |
| 24 | + |
| 25 | ++//TODO: much better estimation than expr_len/2? Such as: |
| 26 | ++//static unsigned estimate_nums_and_names(const char *expr) |
| 27 | ++//{ |
| 28 | ++// unsigned count = 0; |
| 29 | ++// while (*(expr = skip_whitespace(expr)) != '\0') { |
| 30 | ++// const char *p; |
| 31 | ++// if (isdigit(*expr)) { |
| 32 | ++// while (isdigit(*++expr)) |
| 33 | ++// continue; |
| 34 | ++// count++; |
| 35 | ++// continue; |
| 36 | ++// } |
| 37 | ++// p = endofname(expr); |
| 38 | ++// if (p != expr) { |
| 39 | ++// expr = p; |
| 40 | ++// count++; |
| 41 | ++// continue; |
| 42 | ++// } |
| 43 | ++// } |
| 44 | ++// return count; |
| 45 | ++//} |
| 46 | ++ |
| 47 | + static arith_t |
| 48 | + evaluate_string(arith_state_t *math_state, const char *expr) |
| 49 | + { |
| 50 | +@@ -584,10 +606,12 @@ evaluate_string(arith_state_t *math_state, const char *expr) |
| 51 | + const char *errmsg; |
| 52 | + const char *start_expr = expr = skip_whitespace(expr); |
| 53 | + unsigned expr_len = strlen(expr) + 2; |
| 54 | +- /* Stack of integers */ |
| 55 | +- /* The proof that there can be no more than strlen(startbuf)/2+1 |
| 56 | +- * integers in any given correct or incorrect expression |
| 57 | +- * is left as an exercise to the reader. */ |
| 58 | ++ /* Stack of integers/names */ |
| 59 | ++ /* There can be no more than strlen(startbuf)/2+1 |
| 60 | ++ * integers/names in any given correct or incorrect expression. |
| 61 | ++ * (modulo "09v09v09v09v09v" case, |
| 62 | ++ * but we have code to detect that early) |
| 63 | ++ */ |
| 64 | + var_or_num_t *const numstack = alloca((expr_len / 2) * sizeof(numstack[0])); |
| 65 | + var_or_num_t *numstackptr = numstack; |
| 66 | + /* Stack of operator tokens */ |
| 67 | +@@ -652,6 +676,13 @@ evaluate_string(arith_state_t *math_state, const char *expr) |
| 68 | + numstackptr->var = NULL; |
| 69 | + errno = 0; |
| 70 | + numstackptr->val = strto_arith_t(expr, (char**) &expr); |
| 71 | ++ /* A number can't be followed by another number, or a variable name. |
| 72 | ++ * We'd catch this later anyway, but this would require numstack[] |
| 73 | ++ * to be twice as deep to handle strings where _every_ char is |
| 74 | ++ * a new number or name. Example: 09v09v09v09v09v09v09v09v09v |
| 75 | ++ */ |
| 76 | ++ if (isalnum(*expr) || *expr == '_') |
| 77 | ++ goto err; |
| 78 | + //bb_error_msg("val:%lld", numstackptr->val); |
| 79 | + if (errno) |
| 80 | + numstackptr->val = 0; /* bash compat */ |
0 commit comments