]> git.kaiwu.me - njs.git/commitdiff
Fixed heap-use-after-free in JSON.parse().
authorAlexander Borisov <alexander.borisov@nginx.com>
Tue, 6 Oct 2020 16:53:26 +0000 (19:53 +0300)
committerAlexander Borisov <alexander.borisov@nginx.com>
Tue, 6 Oct 2020 16:53:26 +0000 (19:53 +0300)
This correctly fixes the issues addressed in 1405:9beb9ea093b5.
The initial fix wrongly assumed that the "value" pointer is still valid when
njs_is_fast_array(&state->value) is true and the pointer can be used for
the fast path.  This is not the case when the array object is resized.

Moreover, the fast path branch may be completely eliminated because
JSON.parse() with the replacer function is relatively slow by itself.

This closes #323, #324, #325 issues on GitHub.

src/njs_json.c
src/test/njs_unit_test.c

index 80e10cf89421f63258982c6a2e564b5ba997dae4..6bbf13b1fafe9967d1ae5f44bfcd434cee89a59b 100644 (file)
@@ -1018,24 +1018,6 @@ njs_json_parse_iterator_call(njs_vm_t *vm, njs_json_parse_t *parse,
             return ret;
         }
 
-        /*
-         * The njs_function_apply() function can convert fast array to object.
-         * After this conversion, there will be garbage in the value.
-         */
-
-        if (njs_fast_path(njs_is_fast_array(&state->value)
-            && (state->index - 1) < njs_array(&state->value)->length))
-        {
-            if (njs_is_undefined(&parse->retval)) {
-                njs_set_invalid(value);
-
-            } else {
-                *value = parse->retval;
-            }
-
-            break;
-        }
-
         if (njs_is_undefined(&parse->retval)) {
             ret = njs_value_property_i64_delete(vm, &state->value,
                                                 state->index - 1, NULL);
index 661bf6a67fbef7d1b45b4f220e69c70ce28a6df9..64c993cfd67fd6513b01e19c34e2852e74f2c596 100644 (file)
@@ -16437,6 +16437,10 @@ static njs_unit_test_t  njs_test[] =
                  "                   function(k, v) {return v.a.a;}); o"),
       njs_str("TypeError: cannot get property \"a\" of undefined") },
 
+    { njs_str("function func() {this[8] = 1; return new Int8Array(func)}"
+              "JSON.parse('[1]', func);"),
+      njs_str("") },
+
     /* JSON.stringify() */
 
     { njs_str("JSON.stringify()"),