From a851d8a5687356b1d6ad0f8f39d6226947f17b27 Mon Sep 17 00:00:00 2001 From: Sami Vaarala Date: Tue, 11 Jan 2022 01:34:02 +0200 Subject: [PATCH] Fix segfault in call setup when valstack limit hit --- src-input/duk_js_call.c | 14 +++++--- .../ecmascript/test-bug-scope-segv-gh2448.js | 35 +++++++++++++++++++ 2 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 tests/ecmascript/test-bug-scope-segv-gh2448.js diff --git a/src-input/duk_js_call.c b/src-input/duk_js_call.c index 87274c3a..1e933678 100644 --- a/src-input/duk_js_call.c +++ b/src-input/duk_js_call.c @@ -2146,6 +2146,15 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr, duk_idx_t idx_func, d /* [ ... func this arg1 ... argN ] */ + /* + * Grow value stack to required size before env setup. This + * must happen before env setup to handle some corner cases + * correctly, e.g. test-bug-scope-segv-gh2448.js. + */ + + duk_valstack_grow_check_throw(thr, vs_min_bytes); + act->reserve_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack); + /* * Environment record creation and 'arguments' object creation. * Named function expression name binding is handled by the @@ -2167,13 +2176,8 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr, duk_idx_t idx_func, d * Setup value stack: clamp to 'nargs', fill up to 'nregs', * ensure value stack size matches target requirements, and * switch value stack bottom. Valstack top is kept. - * - * Value stack can only grow here. */ - duk_valstack_grow_check_throw(thr, vs_min_bytes); - act->reserve_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack); - if (use_tailcall) { DUK_ASSERT(nregs >= 0); DUK_ASSERT(nregs >= nargs); diff --git a/tests/ecmascript/test-bug-scope-segv-gh2448.js b/tests/ecmascript/test-bug-scope-segv-gh2448.js new file mode 100644 index 00000000..e81783a6 --- /dev/null +++ b/tests/ecmascript/test-bug-scope-segv-gh2448.js @@ -0,0 +1,35 @@ +// https://github.com/svaarala/duktape/issues/2448 + +/*=== +RangeError +===*/ + +function JSEtest() { + var src = []; + var i; + + src.push('(function test() {'); + for (i = 0; i < 1e4; i++) { + src.push('var x' + i + ' = ' + i + ';'); + } + src.push('var arguments = test(); return "dummy"; })'); + src = src.join(''); + //print(src); + + var f = eval(src)(src); + + try { + f(); + } catch (e) { + print(e.name + ': ' + e.message); + } + + print('still here'); +} + +try { + JSEtest(); +} catch (e) { + //print(e.stack || e); + print(e.name); +}