about summary refs log tree commit diff
path: root/Src/math.c
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2012-09-06 18:22:30 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2012-09-06 18:22:30 +0000
commit361e1716729a34d19aa8bace4e6be44c295c3e1d (patch)
treec9a6d68e2f0028a10f8d6088592d9f6073be8d0b /Src/math.c
parent1f5ef83f0f3aea0597ef3db7a05970420646bfdc (diff)
downloadzsh-361e1716729a34d19aa8bace4e6be44c295c3e1d.tar.gz
zsh-361e1716729a34d19aa8bace4e6be44c295c3e1d.tar.xz
zsh-361e1716729a34d19aa8bace4e6be44c295c3e1d.zip
30656: prevent SIGFPE in division by -1 by multiplying instead
Diffstat (limited to 'Src/math.c')
-rw-r--r--Src/math.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/Src/math.c b/Src/math.c
index cca521098..c7d384019 100644
--- a/Src/math.c
+++ b/Src/math.c
@@ -1053,14 +1053,34 @@ op(int what)
 		    return;
 		if (c.type == MN_FLOAT)
 		    c.u.d = a.u.d / b.u.d;
-		else
-		    c.u.l = a.u.l / b.u.l;
+		else {
+		    /*
+		     * Avoid exception when dividing the smallest
+		     * negative integer by -1.  Always treat it the
+		     * same as multiplication.  This still doesn't give
+		     * numerically the right answer in two's complement,
+		     * but treating both these in the same way seems
+		     * reasonable.
+		     */
+		    if (b.u.l == -1)
+			c.u.l = - a.u.l;
+		    else
+			c.u.l = a.u.l / b.u.l;
+		}
 		break;
 	    case MOD:
 	    case MODEQ:
 		if (!notzero(b))
 		    return;
-		c.u.l = a.u.l % b.u.l;
+		/*
+		 * Avoid exception as above.
+		 * Any integer mod -1 is the same as any integer mod 1
+		 * i.e. zero.
+		 */
+		if (b.u.l == -1)
+		    c.u.l = 0;
+		else
+		    c.u.l = a.u.l % b.u.l;
 		break;
 	    case PLUS:
 	    case PLUSEQ: