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) |
