Dmitry Volyntsev
February 21, 2022 12:00PM
details: https://hg.nginx.org/njs/rev/eb8689f0a850
branches:
changeset: 1830:eb8689f0a850
user: Dmitry Volyntsev <xeioex@nginx.com>
date: Mon Feb 21 16:52:59 2022 +0000
description:
Fixed frame allocation from an awaited frame.

njs_function_frame_save() is used to save the awaited frame when "await"
instruction is encountered. The saving was done as a memcpy() of
existing runtime frame.

njs_function_frame_alloc() is used to alloc a new function frame, this
function tries to use a spare preallocated memory from the previous
frame first. Previously, this function might result in "use-after-free"
when invoked from a restored frame saved with njs_function_frame_save().
Because njs_function_frame_save() left pointers to the spare memory of
the original frame which may be already free when saved frame is
restored.

The fix is to erase fields for the spare memory from the saved frame.

This closes #469 issue on Github.

diffstat:

src/njs_function.c | 4 ++++
test/js/async_recursive_large.t.js | 26 ++++++++++++++++++++++++++
test/js/async_recursive_mid.t.js | 2 +-
3 files changed, 31 insertions(+), 1 deletions(-)

diffs (59 lines):

diff -r 5064e36ad7b9 -r eb8689f0a850 src/njs_function.c
--- a/src/njs_function.c Mon Feb 21 16:52:47 2022 +0000
+++ b/src/njs_function.c Mon Feb 21 16:52:59 2022 +0000
@@ -811,9 +811,13 @@ njs_function_frame_save(njs_vm_t *vm, nj
njs_native_frame_t *active, *native;

*frame = *vm->active_frame;
+
frame->previous_active_frame = NULL;

native = &frame->native;
+ native->size = 0;
+ native->free = NULL;
+ native->free_size = 0;

active = &vm->active_frame->native;
value_count = njs_function_frame_value_count(active);
diff -r 5064e36ad7b9 -r eb8689f0a850 test/js/async_recursive_large.t.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/js/async_recursive_large.t.js Mon Feb 21 16:52:59 2022 +0000
@@ -0,0 +1,26 @@
+/*---
+includes: [compareArray.js]
+flags: [async]
+---*/
+
+let stages = [];
+
+async function f(v) {
+ if (v == 1000) {
+ return;
+ }
+
+ stages.push(`f>${v}`);
+
+ await "X";
+
+ await f(v + 1);
+
+ stages.push(`f<${v}`);
+}
+
+f(0)
+.then(v => {
+ assert.sameValue(stages.length, 2000);
+})
+.then($DONE, $DONE);
diff -r 5064e36ad7b9 -r eb8689f0a850 test/js/async_recursive_mid.t.js
--- a/test/js/async_recursive_mid.t.js Mon Feb 21 16:52:47 2022 +0000
+++ b/test/js/async_recursive_mid.t.js Mon Feb 21 16:52:59 2022 +0000
@@ -6,7 +6,7 @@ flags: [async]
let stages = [];

async function f(v) {
- if (v == 3) {
+ if (v == 1000) {
return;
}

_______________________________________________
nginx-devel mailing list -- nginx-devel@nginx.org
To unsubscribe send an email to nginx-devel-leave@nginx.org
Subject Author Views Posted

[njs] Fixed frame allocation from an awaited frame.

Dmitry Volyntsev 606 February 21, 2022 12:00PM



Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 228
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready