Created
April 19, 2019 14:40
-
-
Save lexborisov/6946f9fb8ca76a79f17d9b3a558b8a08 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# HG changeset patch | |
# User Alexander Borisov <alexander.borisov@nginx.com> | |
# Date 1555684207 -10800 | |
# Fri Apr 19 17:30:07 2019 +0300 | |
# Node ID 07b46eb0f25a9ece2f6ad79b834377b72c8f7baf | |
# Parent a6c82ddff460a0d19dd24f6189ce8252954ec41b | |
Added check unsigned int overflow for njs_array_alloc function. | |
diff -r a6c82ddff460 -r 07b46eb0f25a njs/njs_array.c | |
--- a/njs/njs_array.c Fri Apr 19 20:03:49 2019 +0800 | |
+++ b/njs/njs_array.c Fri Apr 19 17:30:07 2019 +0300 | |
@@ -125,22 +125,29 @@ static njs_ret_t njs_array_prototype_sor | |
nxt_noinline njs_array_t * | |
-njs_array_alloc(njs_vm_t *vm, uint32_t length, uint32_t spare) | |
+njs_array_alloc(njs_vm_t *vm, uint64_t length, uint64_t spare) | |
{ | |
uint64_t size; | |
njs_array_t *array; | |
+ if (nxt_slow_path(spare > (UINT64_MAX - length))) { | |
+ goto overflow; | |
+ } | |
+ | |
+ size = length + spare; | |
+ | |
+ if (nxt_slow_path(size > (UINT64_MAX / sizeof(njs_value_t)))) { | |
+ goto overflow; | |
+ | |
+ } else if (nxt_slow_path((size * sizeof(njs_value_t)) >= UINT32_MAX)) { | |
+ goto overflow; | |
+ } | |
+ | |
array = nxt_mp_alloc(vm->mem_pool, sizeof(njs_array_t)); | |
if (nxt_slow_path(array == NULL)) { | |
goto memory_error; | |
} | |
- size = (uint64_t) length + spare; | |
- | |
- if (nxt_slow_path((size * sizeof(njs_value_t)) >= UINT32_MAX)) { | |
- goto memory_error; | |
- } | |
- | |
array->data = nxt_mp_align(vm->mem_pool, sizeof(njs_value_t), | |
size * sizeof(njs_value_t)); | |
if (nxt_slow_path(array->data == NULL)) { | |
@@ -164,6 +171,12 @@ memory_error: | |
njs_memory_error(vm); | |
return NULL; | |
+ | |
+overflow: | |
+ | |
+ njs_range_error(vm, "Invalid array length"); | |
+ | |
+ return NULL; | |
} | |
@@ -266,7 +279,7 @@ njs_array_constructor(njs_vm_t *vm, njs_ | |
if (size == 1 && njs_is_number(&args[0])) { | |
num = args[0].data.u.number; | |
- size = (uint32_t) num; | |
+ size = (uint32_t) (int64_t) num; | |
if ((double) size != num) { | |
njs_range_error(vm, "Invalid array length"); | |
diff -r a6c82ddff460 -r 07b46eb0f25a njs/njs_array.h | |
--- a/njs/njs_array.h Fri Apr 19 20:03:49 2019 +0800 | |
+++ b/njs/njs_array.h Fri Apr 19 17:30:07 2019 +0300 | |
@@ -15,7 +15,7 @@ | |
#define NJS_ARRAY_SPARE 8 | |
-njs_array_t *njs_array_alloc(njs_vm_t *vm, uint32_t length, uint32_t spare); | |
+njs_array_t *njs_array_alloc(njs_vm_t *vm, uint64_t length, uint64_t spare); | |
njs_ret_t njs_array_add(njs_vm_t *vm, njs_array_t *array, njs_value_t *value); | |
njs_ret_t njs_array_string_add(njs_vm_t *vm, njs_array_t *array, | |
const u_char *start, size_t size, size_t length); | |
diff -r a6c82ddff460 -r 07b46eb0f25a njs/test/njs_unit_test.c | |
--- a/njs/test/njs_unit_test.c Fri Apr 19 20:03:49 2019 +0800 | |
+++ b/njs/test/njs_unit_test.c Fri Apr 19 17:30:07 2019 +0300 | |
@@ -7948,7 +7948,13 @@ static njs_unit_test_t njs_test[] = | |
nxt_string("RangeError: Invalid array length") }, | |
{ nxt_string("var a = Array(1111111111)"), | |
- nxt_string("MemoryError") }, | |
+ nxt_string("RangeError: Invalid array length") }, | |
+ | |
+ { nxt_string("var x = Array(2**64)"), | |
+ nxt_string("RangeError: Invalid array length") }, | |
+ | |
+ { nxt_string("var x = Array(2**1000)"), | |
+ nxt_string("RangeError: Invalid array length") }, | |
{ nxt_string("var a = new Array(3); a"), | |
nxt_string(",,") }, | |
# HG changeset patch | |
# User Alexander Borisov <alexander.borisov@nginx.com> | |
# Date 1555683869 -10800 | |
# Fri Apr 19 17:24:29 2019 +0300 | |
# Node ID c1a68ad25fdd4e92f316619465b824bd1f751654 | |
# Parent 07b46eb0f25a9ece2f6ad79b834377b72c8f7baf | |
Fixed overflow in Array.prototype.concat(). | |
This closes #131 issue on GitHub. | |
diff -r 07b46eb0f25a -r c1a68ad25fdd njs/njs_array.c | |
--- a/njs/njs_array.c Fri Apr 19 17:30:07 2019 +0300 | |
+++ b/njs/njs_array.c Fri Apr 19 17:24:29 2019 +0300 | |
@@ -1128,7 +1128,8 @@ static njs_ret_t | |
njs_array_prototype_concat(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, | |
njs_index_t unused) | |
{ | |
- size_t length; | |
+ uint64_t length; | |
+ uint32_t arr_len; | |
nxt_uint_t i; | |
njs_value_t *value; | |
njs_array_t *array; | |
@@ -1137,9 +1138,19 @@ njs_array_prototype_concat(njs_vm_t *vm, | |
for (i = 0; i < nargs; i++) { | |
if (njs_is_array(&args[i])) { | |
- length += args[i].data.u.array->length; | |
+ arr_len = args[i].data.u.array->length; | |
+ | |
+ if (nxt_slow_path(arr_len > (UINT64_MAX - length))) { | |
+ goto overflow; | |
+ } | |
+ | |
+ length += arr_len; | |
} else { | |
+ if (nxt_slow_path(1 > (UINT64_MAX - length))) { | |
+ goto overflow; | |
+ } | |
+ | |
length++; | |
} | |
} | |
@@ -1160,6 +1171,12 @@ njs_array_prototype_concat(njs_vm_t *vm, | |
} | |
return NXT_OK; | |
+ | |
+overflow: | |
+ | |
+ njs_range_error(vm, "Invalid array length"); | |
+ | |
+ return NXT_ERROR; | |
} | |
diff -r 07b46eb0f25a -r c1a68ad25fdd njs/test/njs_unit_test.c | |
--- a/njs/test/njs_unit_test.c Fri Apr 19 17:30:07 2019 +0300 | |
+++ b/njs/test/njs_unit_test.c Fri Apr 19 17:24:29 2019 +0300 | |
@@ -7956,6 +7956,20 @@ static njs_unit_test_t njs_test[] = | |
{ nxt_string("var x = Array(2**1000)"), | |
nxt_string("RangeError: Invalid array length") }, | |
+ /* | |
+ * The exception in the test may differ depending on the amount of memory | |
+ * in the operating system. | |
+ * Out of memory: InternalError | |
+ * Enough memory: RangeError | |
+ */ | |
+ { nxt_string("var r; try {" | |
+ " var x = Array(2**27), y = Array(2**5).fill(x);" | |
+ " Array.prototype.concat.apply(y[0], y.slice(1));" | |
+ "} catch (e) {" | |
+ " r = e.name == 'InternalError' || e.name == 'RangeError'" | |
+ "} r"), | |
+ nxt_string("true") }, | |
+ | |
{ nxt_string("var a = new Array(3); a"), | |
nxt_string(",,") }, | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment