From baedbcb52b52b74bc049e17ca83080b8beeb04e7 Mon Sep 17 00:00:00 2001 From: Igor Sysoev Date: Fri, 21 Oct 2016 23:03:02 +0300 Subject: [PATCH] A fix in Array.prototype.splice() function. Found with afl-fuzz. --- njs/njs_array.c | 39 ++++++++++++++++++++++++++++----------- njs/test/njs_unit_test.c | 9 +++++++++ 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/njs/njs_array.c b/njs/njs_array.c index 149798d9..c93d6c1f 100644 --- a/njs/njs_array.c +++ b/njs/njs_array.c @@ -574,8 +574,8 @@ njs_array_prototype_splice(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, 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, njs_value_t *args, nxt_uint_t nargs, 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, njs_value_t *args, nxt_uint_t nargs, 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 --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c index 86c31abb..cd7a1415 100644 --- a/njs/test/njs_unit_test.c +++ b/njs/test/njs_unit_test.c @@ -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") }, -- 2.47.3