]> git.kaiwu.me - quickjs.git/commitdiff
Fix UB signed integer overflow in js_math_imul
authorCharlie Gordon <github@chqrlie.org>
Sat, 17 Feb 2024 20:15:29 +0000 (21:15 +0100)
committerCharlie Gordon <github@chqrlie.org>
Sat, 17 Feb 2024 20:15:29 +0000 (21:15 +0100)
- 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
quickjs.c
tests/test_builtin.js

index fc59a4fa806aaaad40e18933d725aaeb3abc712b..fe2c03293137db5f39fee9f3c40498d956e37bc0 100644 (file)
--- 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
index 2c1ac6bd662972c18aeb9d33eecd853272e22202..6a34940e928b9988073d8379df18fa35cddcec17 100644 (file)
--- 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,
index a9b2264ed001f79f2edb69c442ce3b89c5d230b9..b6a1c2dac3440974c0ab360d5f93ed8a46a03f99 100644 (file)
@@ -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);