diff --git a/runtime.c b/runtime.c index ae98b2ac..ad46248c 100644 --- a/runtime.c +++ b/runtime.c @@ -3050,17 +3050,14 @@ static int Cyc_checked_sub(int x, int y, int *result) return ((((*result ^ x) & ~(*result ^ y)) >> 30) != 0); } -// Code from http://stackoverflow.com/q/1815367/101258 static int Cyc_checked_mul(int x, int y, int *result) { -// *result = x * y; -// return (*result != 0 && (*result)/x != y) || // Overflow -// (*result > CYC_FIXNUM_MAX) || -// (*result < CYC_FIXNUM_MIN); + // Avoid undefined behavior by detecting overflow prior to multiplication + // Based on code from Hacker's Delight and CHICKEN scheme uint xu, yu, c; - c = 1UL<<31UL; - xu = x < 0 ? -1 : x; - yu = y < 0 ? -1 : y; + c = (1UL<<30UL) - 1; + xu = x < 0 ? -x : x; + yu = y < 0 ? -y : y; if (yu != 0 && xu > (c / yu)) return 1; // Overflow