From 89dd2c275e63704d6a02b756e5f2a02d41ed03ef Mon Sep 17 00:00:00 2001 From: Nick Vatamaniuc Date: Sun, 28 May 2023 01:50:46 -0400 Subject: [PATCH] Fix stack overflow in CVE-2023-31922 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). With ASAN the the poc.js from issue 178: ``` ./qjs ./poc.js InternalError: stack overflow at isArray (native) at (./poc.js:4) ``` Fix: https://github.com/bellard/quickjs/issues/178 --- quickjs.c | 6 ++++++ tests/test_builtin.js | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/quickjs.c b/quickjs.c index b64a59ff1..5ed7da09a 100644 --- a/quickjs.c +++ b/quickjs.c @@ -43631,6 +43631,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 33552d6e3..55cb8e5a1 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();