Diffstat (limited to 'bin/expr/expr.y')
1 files changed, 16 insertions, 4 deletions
diff --git a/bin/expr/expr.y b/bin/expr/expr.y
index 1856ec84d0f7..0ddf3990d2a8 100644
@@ -444,14 +444,26 @@ op_minus(struct val *a, struct val *b)
+ * We depend on undefined behaviour giving a result (in r).
+ * To test this result, pass it as volatile. This prevents
+ * optimizing away of the test based on the undefined behaviour.
-assert_times(intmax_t a, intmax_t b, intmax_t r)
+assert_times(intmax_t a, intmax_t b, volatile intmax_t r)
- * if first operand is 0, no overflow is possible,
- * else result of division test must match second operand
+ * If the first operand is 0, no overflow is possible,
+ * else the result of the division test must match the
+ * second operand.
+ * Be careful to avoid overflow in the overflow test, as
+ * in assert_div(). Overflow in division would kill us
+ * with a SIGFPE before getting the test wrong. In old
+ * buggy versions, optimization used to give a null test
+ * instead of a SIGFPE.
- if (a != 0 && r / a != b)
+ if ((a == -1 && b == INTMAX_MIN) || (a != 0 && r / a != b))