From 08a5dab181fa4c28b7636c35021308e1e12e7b59 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <vda.linux@googlemail.com> Date: Mon, 17 Nov 2014 20:27:18 +0100 Subject: ash: fix handling of negative start value in ${v:start:len} function old new delta subevalvar 1140 1168 +28 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- shell/ash.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 705fe9fa4..90fb00fbd 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -6411,7 +6411,15 @@ subevalvar(char *p, char *varname, int strloc, int subtype, len = number(loc); } } - if (pos >= orig_len) { + if (pos < 0) { + /* ${VAR:$((-n)):l} starts n chars from the end */ + pos = orig_len + pos; + } + if ((unsigned)pos >= orig_len) { + /* apart from obvious ${VAR:999999:l}, + * covers ${VAR:$((-9999999)):l} - result is "" + * (bash-compat) + */ pos = 0; len = 0; } -- cgit v1.2.3-55-g6feb From 8a475def9e3e21f780ebcf07dd607b26ceb00ea8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <vda.linux@googlemail.com> Date: Tue, 18 Nov 2014 14:32:58 +0100 Subject: ash,hush: do not segfault on $((2**63 / -1)) Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- shell/math.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'shell') diff --git a/shell/math.c b/shell/math.c index 3da151137..e7565ebf2 100644 --- a/shell/math.c +++ b/shell/math.c @@ -415,10 +415,29 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ } else if (right_side_val == 0) return "divide by zero"; - else if (op == TOK_DIV || op == TOK_DIV_ASSIGN) - rez /= right_side_val; - else if (op == TOK_REM || op == TOK_REM_ASSIGN) - rez %= right_side_val; + else if (op == TOK_DIV || op == TOK_DIV_ASSIGN + || op == TOK_REM || op == TOK_REM_ASSIGN) { + /* + * bash 4.2.45 x86 64bit: SEGV on 'echo $((2**63 / -1))' + * + * MAX_NEGATIVE_INT / -1 = MAX_POSITIVE_INT+1 + * and thus is not representable. + * Some CPUs segfault trying such op. + * Others overfolw MAX_POSITIVE_INT+1 to + * MAX_NEGATIVE_INT (0x7fff+1 = 0x8000). + * Make sure to at least not SEGV here: + */ + if (right_side_val == -1 + && rez << 1 == 0 /* MAX_NEGATIVE_INT or 0 */ + ) { + right_side_val = 1; + } + if (op == TOK_DIV || op == TOK_DIV_ASSIGN) + rez /= right_side_val; + else { + rez %= right_side_val; + } + } } if (is_assign_op(op)) { -- cgit v1.2.3-55-g6feb From f5add44981b43490376ea0dfed1420dba09a3a75 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <vda.linux@googlemail.com> Date: Thu, 20 Nov 2014 01:43:30 +0100 Subject: typo fix in comment Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- shell/math.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shell') diff --git a/shell/math.c b/shell/math.c index e7565ebf2..006221b6a 100644 --- a/shell/math.c +++ b/shell/math.c @@ -423,7 +423,7 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ * MAX_NEGATIVE_INT / -1 = MAX_POSITIVE_INT+1 * and thus is not representable. * Some CPUs segfault trying such op. - * Others overfolw MAX_POSITIVE_INT+1 to + * Others overflow MAX_POSITIVE_INT+1 to * MAX_NEGATIVE_INT (0x7fff+1 = 0x8000). * Make sure to at least not SEGV here: */ -- cgit v1.2.3-55-g6feb