quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

commit 18c0d5b0fa0d821c4944973bd6798e9ccaf2796e
parent 8d5c41fc538cba48221ef9d8ba9b852e9f04240f
Author: Charlie Gordon <github@chqrlie.org>
Date:   Sat, 17 Feb 2024 21:15:29 +0100

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

Diffstat:
Mquickjs/Makefile | 10++++++++++
Mquickjs/quickjs.c | 12+++++++-----
Mquickjs/tests/test_builtin.js | 4++++
3 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/quickjs/Makefile b/quickjs/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/quickjs.c b/quickjs/quickjs.c @@ -43310,14 +43310,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/quickjs/tests/test_builtin.js b/quickjs/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);