[njs] Fixed njs_vmcode_interpreter() when "toString" conversion fails.

Dmitry Volyntsev xeioex at nginx.com
Tue Apr 5 03:02:31 UTC 2022


details:   https://hg.nginx.org/njs/rev/07ef6c1f04f1
branches:  
changeset: 1833:07ef6c1f04f1
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Mon Mar 28 16:22:17 2022 +0000
description:
Fixed njs_vmcode_interpreter() when "toString" conversion fails.

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

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

This closes #467 issue on Github.

diffstat:

 src/njs_vmcode.c         |  14 ++++++++------
 src/test/njs_unit_test.c |   5 +++++
 2 files changed, 13 insertions(+), 6 deletions(-)

diffs (63 lines):

diff -r 6a5ec4a275a6 -r 07ef6c1f04f1 src/njs_vmcode.c
--- a/src/njs_vmcode.c	Tue Feb 22 19:38:59 2022 +0000
+++ b/src/njs_vmcode.c	Mon Mar 28 16:22:17 2022 +0000
@@ -700,7 +700,7 @@ next:
                 ret = njs_object_prop_define(vm, value1, &name, function,
                                              accessor->type);
                 if (njs_slow_path(ret != NJS_OK)) {
-                    return NJS_ERROR;
+                    goto error;
                 }
 
                 ret = sizeof(njs_vmcode_prop_accessor_t);
@@ -779,12 +779,12 @@ next:
                 }
 
                 if (njs_slow_path(!njs_is_function(&dst))) {
-                    ret = njs_value_to_key(vm, value2, value2);
+                    ret = njs_value_to_key(vm, &dst, value2);
                     if (njs_slow_path(ret != NJS_OK)) {
-                        return NJS_ERROR;
+                        goto error;
                     }
 
-                    njs_key_string_get(vm, value2, &string);
+                    njs_key_string_get(vm, &dst, &string);
                     njs_type_error(vm,
                                "(intermediate value)[\"%V\"] is not a function",
                                &string);
@@ -950,7 +950,8 @@ next:
                 if (njs_is_valid(value1)) {
                     value1 = njs_mp_alloc(vm->mem_pool, sizeof(njs_value_t));
                     if (njs_slow_path(value1 == NULL)) {
-                        return NJS_ERROR;
+                        njs_memory_error(vm);
+                        goto error;
                     }
 
                     njs_scope_value_set(vm, var->dst, value1);
@@ -967,7 +968,8 @@ next:
 
                 value1 = njs_mp_alloc(vm->mem_pool, sizeof(njs_value_t));
                 if (njs_slow_path(value1 == NULL)) {
-                    return NJS_ERROR;
+                    njs_memory_error(vm);
+                    goto error;
                 }
 
                 *value1 = *value2;
diff -r 6a5ec4a275a6 -r 07ef6c1f04f1 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c	Tue Feb 22 19:38:59 2022 +0000
+++ b/src/test/njs_unit_test.c	Mon Mar 28 16:22:17 2022 +0000
@@ -3409,6 +3409,11 @@ static njs_unit_test_t  njs_test[] =
 
     /**/
 
+    { njs_str("function f() { Object.prototype.toString = 1; };"
+              "Object.prototype.toString = f;"
+              "(function () { try { 's'[{}](); } catch (e) { throw e; } })()"),
+      njs_str("TypeError: Cannot convert object to primitive value") },
+
     { njs_str("var i; for (i = 0; i < 10; i++) { i += 1 } i"),
       njs_str("10") },
 



More information about the nginx-devel mailing list