From 045924ed7d3c887cce1c6a22a0b4e0b692719154 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 2 Jul 2023 17:58:20 +0200 Subject: shell/math: do not accept $((36#@)) function old new delta parse_with_base 170 174 +4 arith_apply 996 991 -5 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 4/-5) Total: -1 bytes Signed-off-by: Denys Vlasenko --- shell/math.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/shell/math.c b/shell/math.c index beb89d140..b06d1ae3c 100644 --- a/shell/math.c +++ b/shell/math.c @@ -128,7 +128,8 @@ typedef unsigned char operator; * Consider * and / */ #define tok_decl(prec,id) (((id)<<5) | (prec)) -#define PREC(op) ((op) & 0x1F) +#define ID_SHIFT 5 +#define PREC(op) ((op) & 0x1f) #define PREC_LPAREN 0 #define TOK_LPAREN tok_decl(0,0) @@ -146,14 +147,16 @@ typedef unsigned char operator; #define TOK_AND_ASSIGN tok_decl(2,1) #define TOK_OR_ASSIGN tok_decl(2,2) #define TOK_XOR_ASSIGN tok_decl(2,3) -#define TOK_PLUS_ASSIGN tok_decl(2,4) -#define TOK_MINUS_ASSIGN tok_decl(2,5) +#define TOK_ADD_ASSIGN tok_decl(2,4) +#define TOK_SUB_ASSIGN tok_decl(2,5) #define TOK_LSHIFT_ASSIGN tok_decl(2,6) #define TOK_RSHIFT_ASSIGN tok_decl(2,7) #define PREC_ASSIGN2 3 #define TOK_MUL_ASSIGN tok_decl(3,0) -#define TOK_DIV_ASSIGN tok_decl(3,1) +/* "/" and "/=" ops have the same id bits */ +#define DIV_ID1 1 +#define TOK_DIV_ASSIGN tok_decl(3,DIV_ID1) #define TOK_REM_ASSIGN tok_decl(3,2) #define fix_assignment_prec(prec) do { prec -= (prec == 3); } while (0) @@ -198,7 +201,7 @@ typedef unsigned char operator; #define TOK_SUB tok_decl(13,1) #define TOK_MUL tok_decl(14,0) -#define TOK_DIV tok_decl(14,1) +#define TOK_DIV tok_decl(14,DIV_ID1) #define TOK_REM tok_decl(14,2) /* Exponent is right associative */ @@ -408,9 +411,9 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ rez = (rez <= right_side_val); else if (op == TOK_MUL || op == TOK_MUL_ASSIGN) rez *= right_side_val; - else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN) + else if (op == TOK_ADD || op == TOK_ADD_ASSIGN) rez += right_side_val; - else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN) + else if (op == TOK_SUB || op == TOK_SUB_ASSIGN) rez -= right_side_val; else if (op == TOK_ASSIGN || op == TOK_COMMA) rez = right_side_val; @@ -439,11 +442,11 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ * Make sure to at least not SEGV here: */ if (right_side_val == -1 - && rez << 1 == 0 /* MAX_NEGATIVE_INT or 0 */ + && (rez << 1) == 0 /* MAX_NEGATIVE_INT or 0 */ ) { right_side_val = 1; } - if (op == TOK_DIV || op == TOK_DIV_ASSIGN) + if (op & (DIV_ID1 << ID_SHIFT)) /* DIV or DIV_ASSIGN? */ rez /= right_side_val; else rez %= right_side_val; @@ -505,8 +508,8 @@ static const char op_tokens[] ALIGN1 = { '*','=', 0, TOK_MUL_ASSIGN, '/','=', 0, TOK_DIV_ASSIGN, '%','=', 0, TOK_REM_ASSIGN, - '+','=', 0, TOK_PLUS_ASSIGN, - '-','=', 0, TOK_MINUS_ASSIGN, + '+','=', 0, TOK_ADD_ASSIGN, + '-','=', 0, TOK_SUB_ASSIGN, '-','-', 0, TOK_POST_DEC, '^','=', 0, TOK_XOR_ASSIGN, '+','+', 0, TOK_POST_INC, @@ -542,12 +545,15 @@ static arith_t parse_with_base(const char *nptr, char **endptr, unsigned base) for (;;) { unsigned digit = (unsigned)*nptr - '0'; if (digit >= 10 /* not 0..9 */ - && digit <= 'z' - '0' /* needed to reject e.g. $((64#~)) */ + && digit <= 'z' - '0' /* reject e.g. $((64#~)) */ ) { - /* in bases up to 36, case does not matter for a-z */ + /* current char is one of :;<=>?@A..Z[\]^_`a..z */ + + /* in bases up to 36, case does not matter for a-z, + * map A..Z and a..z to 10..35: */ digit = (unsigned)(*nptr | 0x20) - ('a' - 10); if (base > 36 && *nptr <= '_') { - /* otherwise, A-Z,@,_ are 36-61,62,63 */ + /* base > 36: A-Z,@,_ are 36-61,62,63 */ if (*nptr == '_') digit = 63; else if (*nptr == '@') @@ -558,8 +564,8 @@ static arith_t parse_with_base(const char *nptr, char **endptr, unsigned base) break; /* error: one of [\]^ */ } //bb_error_msg("ch:'%c'%d digit:%u", *nptr, *nptr, digit); - //if (digit < 10) - example where we need this? - // break; + if (digit < 10) /* reject e.g. $((36#@)) */ + break; } if (digit >= base) break; -- cgit v1.2.3