aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2023-06-14 11:33:59 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2023-06-14 11:33:59 +0200
commit3df885abe340c5feaed212536139ee24d60e40a2 (patch)
tree18416785d09ee3f19a3effea7a75b170588ae447
parent5febdb122357dbe39e236c9e93d06dab328edb45 (diff)
downloadbusybox-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.right3
-rwxr-xr-xshell/hush_test/hush-arith/arith-assign-in-varexp.tests8
-rw-r--r--shell/hush_test/hush-arith/arith-comma1.right3
-rwxr-xr-xshell/hush_test/hush-arith/arith-comma1.tests6
-rw-r--r--shell/hush_test/hush-arith/arith-ternary2.right3
-rwxr-xr-xshell/hush_test/hush-arith/arith-ternary2.tests7
-rw-r--r--shell/hush_test/hush-arith/arith-ternary_nested.right1
-rwxr-xr-xshell/hush_test/hush-arith/arith-ternary_nested.tests2
-rw-r--r--shell/math.c27
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 @@
120:20
2a=b=10
3b=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 @@
1exec 2>&1
2a='b=10'
3b=3
4# The variables should evaluate left-to-right,
5# thus b is set to 10 _before_ addition
6echo 20:$((a + b))
7echo "a=$a"
8echo "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 @@
110:10
2a=b=10
3b=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 @@
1exec 2>&1
2a='b=10'
3b=3
4echo 10:$((a,b))
5echo "a=$a"
6echo "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 @@
16:6
2a=b=+err+
3b=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 @@
1exec 2>&1
2a='b=+err+'
3b=5
4# The not-taken branch should not parse variables
5echo 6:$((0 ? a : ++b))
6echo "a=$a"
7echo "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 @@
1exec 2>&1
2echo 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)