From 85fb2caeae86bc7962ff8740f24a3f462e8b3f53 Mon Sep 17 00:00:00 2001 From: Charlie Gordon Date: Sat, 17 Feb 2024 21:15:29 +0100 Subject: [PATCH] Fix UB signed integer overflow in js_math_imul - Use uint32_t arithmetics and Standard conformant conversion to avoid UB in js_math_imul. - add builtin tests - use specific object directories for SAN targets --- Makefile | 10 ++++++++++ quickjs.c | 12 +++++++----- tests/test_builtin.js | 4 ++++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index fc59a4f..fe2c032 100644 --- a/Makefile +++ b/Makefile @@ -56,6 +56,16 @@ CONFIG_BIGNUM=y OBJDIR=.obj +ifdef CONFIG_ASAN +OBJDIR:=$(OBJDIR)/asan +endif +ifdef CONFIG_MSAN +OBJDIR:=$(OBJDIR)/msan +endif +ifdef CONFIG_UBSAN +OBJDIR:=$(OBJDIR)/ubsan +endif + ifdef CONFIG_DARWIN # use clang instead of gcc CONFIG_CLANG=y diff --git a/quickjs.c b/quickjs.c index 2c1ac6b..6a34940 100644 --- a/quickjs.c +++ b/quickjs.c @@ -43092,14 +43092,16 @@ static double js_math_fround(double a) static JSValue js_math_imul(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - int a, b; + uint32_t a, b, c; + int32_t d; - if (JS_ToInt32(ctx, &a, argv[0])) + if (JS_ToUint32(ctx, &a, argv[0])) return JS_EXCEPTION; - if (JS_ToInt32(ctx, &b, argv[1])) + if (JS_ToUint32(ctx, &b, argv[1])) return JS_EXCEPTION; - /* purposely ignoring overflow */ - return JS_NewInt32(ctx, a * b); + c = a * b; + memcpy(&d, &c, sizeof(d)); + return JS_NewInt32(ctx, d); } static JSValue js_math_clz32(JSContext *ctx, JSValueConst this_val, diff --git a/tests/test_builtin.js b/tests/test_builtin.js index a9b2264..b6a1c2d 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);