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>
master
Denys Vlasenko 2023-06-14 11:33:59 +02:00
parent 5febdb1223
commit 3df885abe3
9 changed files with 48 additions and 12 deletions

View File

@ -0,0 +1,3 @@
20:20
a=b=10
b=10

View File

@ -0,0 +1,8 @@
exec 2>&1
a='b=10'
b=3
# The variables should evaluate left-to-right,
# thus b is set to 10 _before_ addition
echo 20:$((a + b))
echo "a=$a"
echo "b=$b"

View File

@ -0,0 +1,3 @@
10:10
a=b=10
b=10

View File

@ -0,0 +1,6 @@
exec 2>&1
a='b=10'
b=3
echo 10:$((a,b))
echo "a=$a"
echo "b=$b"

View File

@ -0,0 +1,3 @@
6:6
a=b=+err+
b=6

View File

@ -0,0 +1,7 @@
exec 2>&1
a='b=+err+'
b=5
# The not-taken branch should not parse variables
echo 6:$((0 ? a : ++b))
echo "a=$a"
echo "b=$b"

View File

@ -0,0 +1 @@
5:5

View File

@ -0,0 +1,2 @@
exec 2>&1
echo 5:$((1?2?3?4?5:6:7:8:9))

View File

@ -340,7 +340,20 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_
if (op == TOK_CONDITIONAL) /* Example: $((a ? b)) */
return "malformed ?: operator";
/* Resolve name to value, if needed */
if (PREC(op) < UNARYPREC) {
/* In binops a ~ b, variables are resolved left-to-right,
* resolve top_of_stack[-1] _before_ resolving top_of_stack[0]
*/
if (top_of_stack == numstack) /* need two arguments */
goto syntax_err;
/* Unless it is =, resolve top_of_stack[-1] name to value */
if (op != TOK_ASSIGN) {
err = arith_lookup_val(math_state, top_of_stack - 1);
if (err)
return err;
}
}
/* Resolve top_of_stack[0] name to value */
err = arith_lookup_val(math_state, top_of_stack);
if (err)
return err;
@ -360,20 +373,10 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_
/* Binary operators */
arith_t right_side_val;
/* Binary operators need two arguments */
if (top_of_stack == numstack)
goto syntax_err;
/* ...and they pop one */
/* Pop numstack */
NUMPTR = top_of_stack; /* this decrements NUMPTR */
top_of_stack--; /* now points to left side */
if (op != TOK_ASSIGN) {
/* Resolve left side value (unless the op is '=') */
err = arith_lookup_val(math_state, top_of_stack);
if (err)
return err;
}
right_side_val = rez;
rez = top_of_stack->val;
if (op == TOK_BOR || op == TOK_OR_ASSIGN)