From d6fbd6b7449e3e808b74ac0f468d1c3557b6741e Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Wed, 1 Nov 2023 09:26:15 +0100 Subject: [PATCH] Fix UB signed integer overflow --- quickjs.c | 6 ++++-- tests/test_builtin.js | 4 ++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/quickjs.c b/quickjs.c index 48e9a38..a2c653e 100644 --- a/quickjs.c +++ b/quickjs.c @@ -41883,8 +41883,10 @@ static JSValue js_math_imul(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; if (JS_ToInt32(ctx, &b, argv[1])) return JS_EXCEPTION; - /* purposely ignoring overflow */ - return JS_NewInt32(ctx, a * b); + /* TODO(bnoordhuis) Signed integral narrowing has implementation-defined + * behavior but that's a step up from the undefined behavior it replaced. + */ + return JS_NewInt32(ctx, (int64_t)a * (int64_t)b); } static JSValue js_math_clz32(JSContext *ctx, JSValueConst this_val, diff --git a/tests/test_builtin.js b/tests/test_builtin.js index c5c0f83..1a6f7b0 100644 --- a/tests/test_builtin.js +++ b/tests/test_builtin.js @@ -311,6 +311,10 @@ function test_math() assert(Math.floor(a), 1); assert(Math.ceil(a), 2); assert(Math.imul(0x12345678, 123), -1088058456); + assert(Math.imul(0xB505, 0xB504), 2147441940); + assert(Math.imul(0xB505, 0xB505), -2147479015); + assert(Math.imul((-2)**31, (-2)**31), 0); + assert(Math.imul(2**31-1, 2**31-1), 1); assert(Math.fround(0.1), 0.10000000149011612); assert(Math.hypot() == 0); assert(Math.hypot(-2) == 2);