From 6b3bed174012a3deecf5269d7654955d21a00df0 Mon Sep 17 00:00:00 2001 From: Nick Vatamaniuc Date: Fri, 1 Dec 2023 10:31:36 -0500 Subject: [PATCH] Fix stack overflow in CVE-2023-31922 (#157) isArray and proxy isArray can call each other indefinitely in a mutually recursive loop. Add a stack overflow check in the js_proxy_isArray function before calling `JS_isArray(ctx, s->target)`. Original issue: https://github.com/bellard/quickjs/issues/178 CVE: https://nvd.nist.gov/vuln/detail/CVE-2023-31922 --- quickjs.c | 6 ++++++ tests/test_builtin.js | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/quickjs.c b/quickjs.c index 86c2fc6..0ee68b4 100644 --- a/quickjs.c +++ b/quickjs.c @@ -43612,6 +43612,12 @@ static int js_proxy_isArray(JSContext *ctx, JSValueConst obj) JSProxyData *s = JS_GetOpaque(obj, JS_CLASS_PROXY); if (!s) return FALSE; + + if (js_check_stack_overflow(ctx->rt, 0)) { + JS_ThrowStackOverflow(ctx); + return -1; + } + if (s->is_revoked) { JS_ThrowTypeErrorRevokedProxy(ctx); return -1; diff --git a/tests/test_builtin.js b/tests/test_builtin.js index 33552d6..6ddea8e 100644 --- a/tests/test_builtin.js +++ b/tests/test_builtin.js @@ -707,6 +707,25 @@ function test_generator() assert(v.value === undefined && v.done === true); } +/* CVE-2023-31922 */ +function test_proxy_is_array() +{ + for (var r = new Proxy([], {}), y = 0; y < 331072; y++) + r = new Proxy(r, {}); + + try { + /* Without ASAN */ + assert(Array.isArray(r)); + } catch(e) { + /* With ASAN expect InternalError "stack overflow" to be raised */ + if (e instanceof InternalError) { + assert(e.message, "stack overflow", "Stack overflow error was not raised") + } else { + throw e; + } + } +} + test(); test_function(); test_enum(); @@ -724,3 +743,4 @@ test_map(); test_weak_map(); test_weak_set(); test_generator(); +test_proxy_is_array();