[njs] Fixed njs_vmcode_interpreter() when await fails.

Dmitry Volyntsev xeioex at nginx.com
Thu Jun 2 23:33:29 UTC 2022


details:   https://hg.nginx.org/njs/rev/e99d83c24517
branches:  
changeset: 1873:e99d83c24517
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Thu Jun 02 16:32:38 2022 -0700
description:
Fixed njs_vmcode_interpreter() when await fails.

Previously, while interpreting a user function, njs_vmcode_interpreter()
might return prematurely when an error happens in await instruction.
This is not correct because the current frame has to be unwound (or
exception caught) first.

The fix is to exit through only 5 appropriate exit points to ensure
proper unwinding.

The patch correctly fixes issue reported in 07ef6c1f04f1 (0.7.3).

This closes #506 issue on Github.

diffstat:

 src/njs_vmcode.c                      |   9 ++++++++-
 test/js/async_exception_in_await.t.js |  22 ++++++++++++++++++++++
 2 files changed, 30 insertions(+), 1 deletions(-)

diffs (54 lines):

diff -r ddec2f61c6d4 -r e99d83c24517 src/njs_vmcode.c
--- a/src/njs_vmcode.c	Wed Jun 01 21:54:32 2022 -0700
+++ b/src/njs_vmcode.c	Thu Jun 02 16:32:38 2022 -0700
@@ -856,9 +856,15 @@ next:
             case NJS_VMCODE_AWAIT:
                 await = (njs_vmcode_await_t *) pc;
 
+                ret = njs_vmcode_await(vm, await, promise_cap, async_ctx);
+
                 njs_vmcode_debug(vm, pc, "EXIT AWAIT");
 
-                return njs_vmcode_await(vm, await, promise_cap, async_ctx);
+                if (njs_slow_path(ret == NJS_ERROR)) {
+                    goto error;
+                }
+
+                return ret;
 
             case NJS_VMCODE_TRY_START:
                 ret = njs_vmcode_try_start(vm, value1, value2, pc);
@@ -1923,6 +1929,7 @@ njs_vmcode_await(njs_vm_t *vm, njs_vmcod
 
     value = njs_scope_valid_value(vm, await->retval);
     if (njs_slow_path(value == NULL)) {
+        njs_internal_error(vm, "await->retval is invalid");
         return NJS_ERROR;
     }
 
diff -r ddec2f61c6d4 -r e99d83c24517 test/js/async_exception_in_await.t.js
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/js/async_exception_in_await.t.js	Thu Jun 02 16:32:38 2022 -0700
@@ -0,0 +1,22 @@
+/*---
+includes: []
+flags: []
+---*/
+
+var p = new Promise(() => 0);
+Object.defineProperty(p, "constructor", {get: () => ({}).a.a});
+
+async function g() {
+    try {
+        await p;
+    } catch (e) {
+    }
+}
+
+function f() {
+    g();
+
+    return 42;
+}
+
+assert.sameValue(f(), 42);



More information about the nginx-devel mailing list