[njs] Fixed heap-use-after-free in JSON.parse() function.

Alexander Borisov alexander.borisov at nginx.com
Wed May 27 15:19:39 UTC 2020


details:   https://hg.nginx.org/njs/rev/9beb9ea093b5
branches:  
changeset: 1405:9beb9ea093b5
user:      Alexander Borisov <alexander.borisov at nginx.com>
date:      Wed May 27 18:18:40 2020 +0300
description:
Fixed heap-use-after-free in JSON.parse() function.

diffstat:

 src/njs_json.c           |  24 ++++++++++++++++++++++--
 src/test/njs_unit_test.c |  17 +++++++++++++++++
 2 files changed, 39 insertions(+), 2 deletions(-)

diffs (64 lines):

diff -r 4fb07fcbb698 -r 9beb9ea093b5 src/njs_json.c
--- a/src/njs_json.c	Wed May 27 12:02:59 2020 +0000
+++ b/src/njs_json.c	Wed May 27 18:18:40 2020 +0300
@@ -1018,11 +1018,31 @@ njs_json_parse_iterator_call(njs_vm_t *v
             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)) {
-            njs_set_invalid(value);
+            njs_value_property_i64_delete(vm, &state->value, state->index - 1,
+                                          NULL);
 
         } else {
-            *value = parse->retval;
+            njs_value_property_i64_set(vm, &state->value, state->index - 1,
+                                       &parse->retval);
         }
 
         break;
diff -r 4fb07fcbb698 -r 9beb9ea093b5 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c	Wed May 27 12:02:59 2020 +0000
+++ b/src/test/njs_unit_test.c	Wed May 27 18:18:40 2020 +0300
@@ -15309,6 +15309,23 @@ static njs_unit_test_t  njs_test[] =
                  "args.join('|')"),
       njs_str("0:2|a:3|1:[object Object]|:2,[object Object]") },
 
+    { njs_str("JSON.parse('[0,1,2]', function(k, v) {"
+              "    if (v == 2) {"
+              "        return undefined;"
+              "    }"
+              "    return v;"
+              "});"),
+      njs_str("0,1,") },
+
+    { njs_str("JSON.parse('[0,1,2]', function(k, v) {"
+              "    if (v == 0) {"
+              "        Object.defineProperty(this, '0', {value: undefined, enumerable: false});"
+              "        return undefined;"
+              "    }"
+              "    return v;"
+              "});"),
+      njs_str(",1,2") },
+
     { njs_str("JSON.parse()"),
       njs_str("SyntaxError: Unexpected token at position 0") },
 


More information about the nginx-devel mailing list