diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2023-06-14 11:33:59 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2023-06-14 11:33:59 +0200 |
commit | 3df885abe340c5feaed212536139ee24d60e40a2 (patch) | |
tree | 18416785d09ee3f19a3effea7a75b170588ae447 | |
parent | 5febdb122357dbe39e236c9e93d06dab328edb45 (diff) | |
download | busybox-w32-3df885abe340c5feaed212536139ee24d60e40a2.tar.gz busybox-w32-3df885abe340c5feaed212536139ee24d60e40a2.tar.bz2 busybox-w32-3df885abe340c5feaed212536139ee24d60e40a2.zip |
shell/math: fix the order of variable resolution in binops
function old new delta
arith_apply 1134 1143 +9
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/hush_test/hush-arith/arith-assign-in-varexp.right | 3 | ||||
-rwxr-xr-x | shell/hush_test/hush-arith/arith-assign-in-varexp.tests | 8 | ||||
-rw-r--r-- | shell/hush_test/hush-arith/arith-comma1.right | 3 | ||||
-rwxr-xr-x | shell/hush_test/hush-arith/arith-comma1.tests | 6 | ||||
-rw-r--r-- | shell/hush_test/hush-arith/arith-ternary2.right | 3 | ||||
-rwxr-xr-x | shell/hush_test/hush-arith/arith-ternary2.tests | 7 | ||||
-rw-r--r-- | shell/hush_test/hush-arith/arith-ternary_nested.right | 1 | ||||
-rwxr-xr-x | shell/hush_test/hush-arith/arith-ternary_nested.tests | 2 | ||||
-rw-r--r-- | shell/math.c | 27 |
9 files changed, 48 insertions, 12 deletions
diff --git a/shell/hush_test/hush-arith/arith-assign-in-varexp.right b/shell/hush_test/hush-arith/arith-assign-in-varexp.right new file mode 100644 index 000000000..06ac80a64 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-assign-in-varexp.right | |||
@@ -0,0 +1,3 @@ | |||
1 | 20:20 | ||
2 | a=b=10 | ||
3 | b=10 | ||
diff --git a/shell/hush_test/hush-arith/arith-assign-in-varexp.tests b/shell/hush_test/hush-arith/arith-assign-in-varexp.tests new file mode 100755 index 000000000..920aaa779 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-assign-in-varexp.tests | |||
@@ -0,0 +1,8 @@ | |||
1 | exec 2>&1 | ||
2 | a='b=10' | ||
3 | b=3 | ||
4 | # The variables should evaluate left-to-right, | ||
5 | # thus b is set to 10 _before_ addition | ||
6 | echo 20:$((a + b)) | ||
7 | echo "a=$a" | ||
8 | echo "b=$b" | ||
diff --git a/shell/hush_test/hush-arith/arith-comma1.right b/shell/hush_test/hush-arith/arith-comma1.right new file mode 100644 index 000000000..be1264cc0 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-comma1.right | |||
@@ -0,0 +1,3 @@ | |||
1 | 10:10 | ||
2 | a=b=10 | ||
3 | b=10 | ||
diff --git a/shell/hush_test/hush-arith/arith-comma1.tests b/shell/hush_test/hush-arith/arith-comma1.tests new file mode 100755 index 000000000..f86304303 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-comma1.tests | |||
@@ -0,0 +1,6 @@ | |||
1 | exec 2>&1 | ||
2 | a='b=10' | ||
3 | b=3 | ||
4 | echo 10:$((a,b)) | ||
5 | echo "a=$a" | ||
6 | echo "b=$b" | ||
diff --git a/shell/hush_test/hush-arith/arith-ternary2.right b/shell/hush_test/hush-arith/arith-ternary2.right new file mode 100644 index 000000000..a549b1b5c --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary2.right | |||
@@ -0,0 +1,3 @@ | |||
1 | 6:6 | ||
2 | a=b=+err+ | ||
3 | b=6 | ||
diff --git a/shell/hush_test/hush-arith/arith-ternary2.tests b/shell/hush_test/hush-arith/arith-ternary2.tests new file mode 100755 index 000000000..cb3163932 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary2.tests | |||
@@ -0,0 +1,7 @@ | |||
1 | exec 2>&1 | ||
2 | a='b=+err+' | ||
3 | b=5 | ||
4 | # The not-taken branch should not parse variables | ||
5 | echo 6:$((0 ? a : ++b)) | ||
6 | echo "a=$a" | ||
7 | echo "b=$b" | ||
diff --git a/shell/hush_test/hush-arith/arith-ternary_nested.right b/shell/hush_test/hush-arith/arith-ternary_nested.right new file mode 100644 index 000000000..aa54bd925 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary_nested.right | |||
@@ -0,0 +1 @@ | |||
5:5 | |||
diff --git a/shell/hush_test/hush-arith/arith-ternary_nested.tests b/shell/hush_test/hush-arith/arith-ternary_nested.tests new file mode 100755 index 000000000..eefc8e7ce --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary_nested.tests | |||
@@ -0,0 +1,2 @@ | |||
1 | exec 2>&1 | ||
2 | echo 5:$((1?2?3?4?5:6:7:8:9)) | ||
diff --git a/shell/math.c b/shell/math.c index fa22bc400..077aba848 100644 --- a/shell/math.c +++ b/shell/math.c | |||
@@ -340,7 +340,20 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ | |||
340 | if (op == TOK_CONDITIONAL) /* Example: $((a ? b)) */ | 340 | if (op == TOK_CONDITIONAL) /* Example: $((a ? b)) */ |
341 | return "malformed ?: operator"; | 341 | return "malformed ?: operator"; |
342 | 342 | ||
343 | /* Resolve name to value, if needed */ | 343 | if (PREC(op) < UNARYPREC) { |
344 | /* In binops a ~ b, variables are resolved left-to-right, | ||
345 | * resolve top_of_stack[-1] _before_ resolving top_of_stack[0] | ||
346 | */ | ||
347 | if (top_of_stack == numstack) /* need two arguments */ | ||
348 | goto syntax_err; | ||
349 | /* Unless it is =, resolve top_of_stack[-1] name to value */ | ||
350 | if (op != TOK_ASSIGN) { | ||
351 | err = arith_lookup_val(math_state, top_of_stack - 1); | ||
352 | if (err) | ||
353 | return err; | ||
354 | } | ||
355 | } | ||
356 | /* Resolve top_of_stack[0] name to value */ | ||
344 | err = arith_lookup_val(math_state, top_of_stack); | 357 | err = arith_lookup_val(math_state, top_of_stack); |
345 | if (err) | 358 | if (err) |
346 | return err; | 359 | return err; |
@@ -360,20 +373,10 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ | |||
360 | /* Binary operators */ | 373 | /* Binary operators */ |
361 | arith_t right_side_val; | 374 | arith_t right_side_val; |
362 | 375 | ||
363 | /* Binary operators need two arguments */ | 376 | /* Pop numstack */ |
364 | if (top_of_stack == numstack) | ||
365 | goto syntax_err; | ||
366 | /* ...and they pop one */ | ||
367 | NUMPTR = top_of_stack; /* this decrements NUMPTR */ | 377 | NUMPTR = top_of_stack; /* this decrements NUMPTR */ |
368 | top_of_stack--; /* now points to left side */ | 378 | top_of_stack--; /* now points to left side */ |
369 | 379 | ||
370 | if (op != TOK_ASSIGN) { | ||
371 | /* Resolve left side value (unless the op is '=') */ | ||
372 | err = arith_lookup_val(math_state, top_of_stack); | ||
373 | if (err) | ||
374 | return err; | ||
375 | } | ||
376 | |||
377 | right_side_val = rez; | 380 | right_side_val = rez; |
378 | rez = top_of_stack->val; | 381 | rez = top_of_stack->val; |
379 | if (op == TOK_BOR || op == TOK_OR_ASSIGN) | 382 | if (op == TOK_BOR || op == TOK_OR_ASSIGN) |