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