[prev in list] [next in list] [prev in thread] [next in thread]
List: busybox
Subject: [PATCH] shell: $(()): fix two more (?: whiteout related) errors
From: Steffen Nurpmeso <steffen () sdaoden ! eu>
Date: 2022-08-19 17:00:47
Message-ID: b01fed3cfac89259bcfaf212611d675f9ac5aa68.1660926701.git.steffen () sdaoden ! eu
[Download RAW message or body]
---
20220818231006.ZYhYJ%steffen@sdaoden.eu:
I just fixed two other bugs regarding $: ternary resolution which
affect strange cases regarding precedence in whiteouts
$((0?I1=10:(1?I3:I2=12)))
vs
$((0?I1=10:(0?I3:I2=12)))
as well as a missing variable-expansion prevention in a whiteout.
(Let me allow to keep saying whiteout, please.)
It bugs me. "Three line fix", so to say.
Locally i added a couple of more tests, and i am now really out of
ideas what other tests i could throw at the code.
Sorry again for now waiting until i had an iteration.
[.]I will send the small bugfix patch onto v2 tomorrow,[.]
It is a bit larger than it could be because it adds a dedicated
error constant, as well as renaming another one.
shell/math.c | 5 +++--
shell/shexp-arith.h | 53 ++++++++++++++++++++++++++++++---------------
2 files changed, 38 insertions(+), 20 deletions(-)
diff --git a/shell/math.c b/shell/math.c
index a20596089d..8388fdecad 100644
--- a/shell/math.c
+++ b/shell/math.c
@@ -214,7 +214,7 @@ static arith_t strto_arith_t(const char *nptr, char **endptr)
#define CONCAT(S1,S2) su__CONCAT_1(S1, S2)
# define su__CONCAT_1(S1,S2) su__CONCAT_2(S1, S2)
# define su__CONCAT_2(S1,S2) S1 ## S2
-#define DBG(X)
+#define DBGX(X)
#define FALLTHRU
#define N_(X) X
#define NIL NULL
@@ -299,8 +299,9 @@ arith(arith_state_t *math_state, const char *expr)
a_X(ASSIGN_NO_VAR, "assignment without variable");
a_X(DIV_BY_ZERO, "division by zero");
a_X(EXP_INVALID, "invalid exponent");
- a_X(NO_OPERAND, "syntax error, expected operand");
+ a_X(NO_OP, "syntax error, expected operand");
a_X(COND_NO_COLON, "syntax error, incomplete ?: condition");
+ a_X(COND_PREC_INVALID, "?: condition, invalid precedence (1:v2:v3=3)");
a_X(NAME_LOOP, "recursive variable name reference");
a_X(OP_INVALID, "unknown operator");
}
diff --git a/shell/shexp-arith.h b/shell/shexp-arith.h
index f48ada1b46..fa44d4234d 100644
--- a/shell/shexp-arith.h
+++ b/shell/shexp-arith.h
@@ -47,8 +47,9 @@ enum a_shexp_arith_error{
a_SHEXP_ARITH_ERR_ASSIGN_NO_VAR, /* Assignment without variable */
a_SHEXP_ARITH_ERR_DIV_BY_ZERO,
a_SHEXP_ARITH_ERR_EXP_INVALID, /* Invalid exponent */
- a_SHEXP_ARITH_ERR_NO_OPERAND, /* Expected an argument here */
+ a_SHEXP_ARITH_ERR_NO_OP, /* Expected an argument here */
a_SHEXP_ARITH_ERR_COND_NO_COLON, /* Incomplete ?: condition */
+ a_SHEXP_ARITH_ERR_COND_PREC_INVALID, /* 1 ? VAR1 : VAR2 = 3 */
a_SHEXP_ARITH_ERR_NAME_LOOP, /* Variable self-reference loop */
a_SHEXP_ARITH_ERR_OP_INVALID /* Unknown operator */
};
@@ -269,10 +270,10 @@ a_shexp_arith_eval(
#endif
ASSERT_NYD_EXEC(resp != NIL,
- self.sac_error = a_SHEXP_ARITH_ERR_NO_OPERAND);
- DBG( *resp = 0; )
+ self.sac_error = a_SHEXP_ARITH_ERR_NO_OP);
+ DBGX( *resp = 0; )
ASSERT_NYD_EXEC(exp_len == 0 || exp_buf != NIL,
- self.sac_error = a_SHEXP_ARITH_ERR_NO_OPERAND);
+ self.sac_error = a_SHEXP_ARITH_ERR_NO_OP);
a_SHEXP_ARITH_IFS( self.sac_ifs_ws = ok_vlook(ifs_ws); )
self.sac_stack = &sas_stack;
@@ -425,6 +426,7 @@ a_shexp__arith_eval(struct a_shexp_arith_ctx *self,
++sasp->sas_nums_top;
lop = a_SHEXP_ARITH_OP_NUM;
+
a_SHEXP_ARITH_L((" + _arith_eval VAR <%s>\n",
sasp->sas_nums_top[-1].sav_var));
continue;
@@ -533,7 +535,7 @@ junapre:
prec < a_SHEXP_ARITH_PREC_UNARY) ||
prec >= a_SHEXP_ARITH_PREC_SKY){
if(lop != a_SHEXP_ARITH_OP_NUM){
- self->sac_error = a_SHEXP_ARITH_ERR_NO_OPERAND;
+ self->sac_error = a_SHEXP_ARITH_ERR_NO_OP;
goto jleave;
}
@@ -594,9 +596,11 @@ junapre:
ASSERT(sasp->sas_nums_top > sasp->sas_nums);
--sasp->sas_nums_top;
- if((op & a_SHEXP_ARITH_OP_MASK) != a_SHEXP_ARITH_OP_ASSIGN &&
- sasp->sas_nums_top->sav_var != NIL){
- if(!a_shexp__arith_val_eval(self, sasp->sas_nums_top))
+ if(sasp->sas_nums_top->sav_var != NIL){
+ if(!(op & a_SHEXP_ARITH_OP_FLAG_WHITE_MASK) &&
+ (op & a_SHEXP_ARITH_OP_MASK) !=
+ a_SHEXP_ARITH_OP_ASSIGN &&
+ !a_shexp__arith_val_eval(self, sasp->sas_nums_top))
goto jleave;
sasp->sas_nums_top->sav_var = NIL;
}
@@ -669,17 +673,29 @@ junapre:
}
/* Is this a right-associative operation? */
else{
- boole doit=FAL0;
+ boole doit;
+ doit = FAL0;
if(lprec < prec){
doit = TRU1;
a_SHEXP_ARITH_L((" + _arith_eval DELAY PRECEDENCE\n"));
}else if(lprec == prec && prec == a_SHEXP_ARITH_PREC_ASSIGN){
doit = TRU1;
a_SHEXP_ARITH_L((" + _arith_eval DELAY RIGHT ASSOC\n"));
- }else if(lop == a_SHEXP_ARITH_OP_COND){
- doit = TRU1;
- a_SHEXP_ARITH_L((" + _arith_eval DELAY CONDITION\n"));
+ }else if(lprec == a_SHEXP_ARITH_PREC_COND){
+ if(lop == a_SHEXP_ARITH_OP_COND){
+ doit = TRU1;
+ a_SHEXP_ARITH_L((" + _arith_eval DELAY CONDITION\n"));
+ }
+ /* Without massive rewrite this is the location to detect
+ * in-whiteout precedence bugs as in
+ * $((0?I1=10:(1?I3:I2=12)))
+ * which would be parsed like (1?I3:I2)=12 without error
+ * (different to 0?I3:I2=12) otherwise */
+ else if(op != a_SHEXP_ARITH_OP_COMMA){
+ self->sac_error = a_SHEXP_ARITH_ERR_COND_PREC_INVALID;
+ goto jleave;
+ }
}
if(doit){
@@ -887,7 +903,7 @@ a_shexp__arith_op_apply(struct a_shexp_arith_ctx *self){
/* At least one argument is always needed */
if((nums_top = sasp->sas_nums_top) == sasp->sas_nums){
- self->sac_error = a_SHEXP_ARITH_ERR_NO_OPERAND;
+ self->sac_error = a_SHEXP_ARITH_ERR_NO_OP;
goto jleave;
}
--nums_top;
@@ -922,7 +938,9 @@ a_shexp__arith_op_apply(struct a_shexp_arith_ctx *self){
}
goto jquick;
}else if(op == a_SHEXP_ARITH_OP_COND_COLON){
+ ASSERT(sasp->sas_ops_top > sasp->sas_ops);
ASSERT(nums_top > sasp->sas_nums);
+
if(!ign){
/* Move the ternary value over to LHV where we find it as a result,
* and ensure LHV's name is forgotten so not to evaluate it (for
@@ -930,18 +948,17 @@ a_shexp__arith_op_apply(struct a_shexp_arith_ctx *self){
* outer group, because it still exists on number stack) */
nums_top[-1].sav_val = nums_top[0].sav_val;
nums_top[-1].sav_var = NIL;
- }else{
+ }else
val = nums_top[-1].sav_val;
- /*nums_top[0].sav_var = NIL;*/
- }
+
sasp->sas_nums_top = nums_top;
- ASSERT(sasp->sas_ops_top > sasp->sas_ops);
if((sasp->sas_ops_top[-1] & a_SHEXP_ARITH_OP_MASK
) == a_SHEXP_ARITH_OP_COND_COLON){
--sasp->sas_ops_top;
if(!a_shexp__arith_op_apply_colons(self))
goto jleave;
+ ASSERT(sasp->sas_nums_top > sasp->sas_nums);
if(!ign)
sasp->sas_nums_top[-1].sav_val = val;
}
@@ -950,7 +967,7 @@ a_shexp__arith_op_apply(struct a_shexp_arith_ctx *self){
s64 rval;
if(nums_top == sasp->sas_nums){
- self->sac_error = a_SHEXP_ARITH_ERR_NO_OPERAND;
+ self->sac_error = a_SHEXP_ARITH_ERR_NO_OP;
goto jleave;
}
sasp->sas_nums_top = nums_top--;
--
2.37.2
--steffen
|
|Der Kragenbaer, The moon bear,
|der holt sich munter he cheerfully and one by one
|einen nach dem anderen runter wa.ks himself off
|(By Robert Gernhardt)
_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic