[njs] A fix in Array.prototype.splice() function.

Igor Sysoev igor at sysoev.ru
Fri Oct 21 20:05:31 UTC 2016


details:   http://hg.nginx.org/njs/rev/7685bf403554
branches:  
changeset: 210:7685bf403554
user:      Igor Sysoev <igor at sysoev.ru>
date:      Fri Oct 21 23:03:02 2016 +0300
description:
A fix in Array.prototype.splice() function.

Found with afl-fuzz.

diffstat:

 njs/njs_array.c          |  39 ++++++++++++++++++++++++++++-----------
 njs/test/njs_unit_test.c |   9 +++++++++
 2 files changed, 37 insertions(+), 11 deletions(-)

diffs (97 lines):

diff -r b290544f11bc -r 7685bf403554 njs/njs_array.c
--- a/njs/njs_array.c	Thu Oct 20 17:12:42 2016 +0300
+++ b/njs/njs_array.c	Fri Oct 21 23:03:02 2016 +0300
@@ -574,8 +574,8 @@ njs_array_prototype_splice(njs_vm_t *vm,
     njs_index_t unused)
 {
     njs_ret_t    ret;
-    nxt_int_t    items, delta;
-    nxt_uint_t   i, n, start, delete, length;
+    nxt_int_t    n, start, length, items, delta, delete;
+    nxt_uint_t   i;
     njs_array_t  *array, *deleted;
 
     array = NULL;
@@ -584,19 +584,33 @@ njs_array_prototype_splice(njs_vm_t *vm,
 
     if (njs_is_array(&args[0])) {
         array = args[0].data.u.array;
+        length = array->length;
 
         if (nargs > 1) {
             start = args[1].data.u.number;
 
-            if (start > array->length) {
-                start = array->length;
+            if (start < 0) {
+                start += length;
+
+                if (start < 0) {
+                    start = 0;
+                }
+
+            } else if (start > length) {
+                start = length;
             }
 
+            delete = length - start;
+
             if (nargs > 2) {
-                delete = args[2].data.u.number;
+                n = args[2].data.u.number;
 
-            } else {
-                delete = array->length - start;
+                if (n < 0) {
+                    delete = 0;
+
+                } else if (n < delete) {
+                    delete = n;
+                }
             }
         }
     }
@@ -606,17 +620,20 @@ njs_array_prototype_splice(njs_vm_t *vm,
         return NXT_ERROR;
     }
 
-    if (array != NULL && (delete != 0 || nargs > 3)) {
-        length = array->length;
+    if (array != NULL && (delete >= 0 || nargs > 3)) {
 
         /* Move deleted items to a new array to return. */
-        for (i = 0, n = start; i < delete && n < length; i++, n++) {
+        for (i = 0, n = start; i < (nxt_uint_t) delete; i++, n++) {
             /* No retention required. */
             deleted->start[i] = array->start[n];
         }
 
         items = nargs - 3;
-        items = items >= 0 ? items : 0;
+
+        if (items < 0) {
+            items = 0;
+        }
+
         delta = items - delete;
 
         if (delta != 0) {
diff -r b290544f11bc -r 7685bf403554 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c	Thu Oct 20 17:12:42 2016 +0300
+++ b/njs/test/njs_unit_test.c	Fri Oct 21 23:03:02 2016 +0300
@@ -2316,6 +2316,15 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("var a = []; a.splice()"),
       nxt_string("") },
 
+    { nxt_string("[].splice(0,5,0)"),
+      nxt_string("") },
+
+    { nxt_string("[1,2,3,4,5].splice(-2,3,0)"),
+      nxt_string("4,5") },
+
+    { nxt_string("[].__proto__.splice(0,1,0)"),
+      nxt_string("") },
+
     { nxt_string("var a = [];"
                  "a.splice(9,0,1,2).join(':') + '|' + a"),
       nxt_string("|1,2") },



More information about the nginx-devel mailing list