[njs] Added support for detached-buffers.
Dmitry Volyntsev
xeioex at nginx.com
Mon Sep 21 12:11:19 UTC 2020
details: https://hg.nginx.org/njs/rev/f7f7994b69b5
branches:
changeset: 1525:f7f7994b69b5
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Fri Sep 18 18:00:32 2020 +0000
description:
Added support for detached-buffers.
diffstat:
auto/cc | 4 +
auto/help | 6 +-
auto/options | 4 +-
src/njs_array_buffer.c | 4 +
src/njs_buffer.c | 90 ++++++++++++++++---
src/njs_builtin.c | 69 +++++++++++++++
src/njs_object_hash.h | 8 +
src/njs_typed_array.c | 209 ++++++++++++++++++++++++++++++++++++++--------
src/njs_value.c | 10 ++
src/njs_value.h | 4 +
src/njs_vm.h | 5 +-
src/test/njs_unit_test.c | 4 +
12 files changed, 360 insertions(+), 57 deletions(-)
diffs (905 lines):
diff -r 0cfc928cc1e4 -r f7f7994b69b5 auto/cc
--- a/auto/cc Thu Sep 17 13:10:51 2020 +0300
+++ b/auto/cc Fri Sep 18 18:00:32 2020 +0000
@@ -177,5 +177,9 @@ if [ "$NJS_DEBUG_MEMORY" = "YES" ]; then
njs_define=NJS_DEBUG_MEMORY . auto/define
fi
+if [ "$NJS_TEST262" = "YES" ]; then
+ njs_define=NJS_TEST262 . auto/define
+fi
+
# Stop on error exit status again.
set -e
diff -r 0cfc928cc1e4 -r f7f7994b69b5 auto/help
--- a/auto/help Thu Sep 17 13:10:51 2020 +0300
+++ b/auto/help Fri Sep 18 18:00:32 2020 +0000
@@ -14,10 +14,12 @@ default: "$NJS_CC_OPT"
default: "$NJS_LD_OPT"
--ar=FILE set static linking program, default: "$AR"
+ --address-sanitizer=YES enables build with address sanitizer, \
+default: "$NJS_ADDRESS_SANITIZER"
--debug=YES enables additional runtime checks, \
default: "$NJS_DEBUG"
--debug-memory=YES enables memory alloc debug, \
default: "$NJS_DEBUG_MEMORY"
- --address-sanitizer=YES enables build with address sanitizer, \
-default: "$NJS_ADDRESS_SANITIZER"
+ --test262=YES enables test262 extentions, \
+default: "$NJS_TEST262"
END
diff -r 0cfc928cc1e4 -r f7f7994b69b5 auto/options
--- a/auto/options Thu Sep 17 13:10:51 2020 +0300
+++ b/auto/options Fri Sep 18 18:00:32 2020 +0000
@@ -9,6 +9,7 @@ NJS_LD_OPT=${NJS_CC_OPT:--O}
NJS_DEBUG=NO
NJS_DEBUG_MEMORY=NO
NJS_ADDRESS_SANITIZER=NO
+NJS_TEST262=YES
NJS_CONFIGURE_OPTIONS=
@@ -25,9 +26,10 @@ do
--ld-opt=*) NJS_LD_OPT="$value" ;;
--ar=*) AR="$value" ;;
+ --address-sanitizer=*) NJS_ADDRESS_SANITIZER="$value" ;;
--debug=*) NJS_DEBUG="$value" ;;
--debug-memory=*) NJS_DEBUG_MEMORY="$value" ;;
- --address-sanitizer=*) NJS_ADDRESS_SANITIZER="$value" ;;
+ --test262=*) NJS_TEST262="$value" ;;
--help)
. auto/help
diff -r 0cfc928cc1e4 -r f7f7994b69b5 src/njs_array_buffer.c
--- a/src/njs_array_buffer.c Thu Sep 17 13:10:51 2020 +0300
+++ b/src/njs_array_buffer.c Fri Sep 18 18:00:32 2020 +0000
@@ -204,6 +204,10 @@ njs_array_buffer_prototype_byte_length(n
}
array = njs_array_buffer(value);
+ if (njs_slow_path(njs_is_detached_buffer(array))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
njs_set_number(&vm->retval, array->size);
diff -r 0cfc928cc1e4 -r f7f7994b69b5 src/njs_buffer.c
--- a/src/njs_buffer.c Thu Sep 17 13:10:51 2020 +0300
+++ b/src/njs_buffer.c Fri Sep 18 18:00:32 2020 +0000
@@ -441,6 +441,11 @@ njs_buffer_from_typed_array(njs_vm_t *vm
njs_typed_array_t *buffer, *array;
array = njs_typed_array(value);
+ if (njs_slow_path(njs_is_detached_buffer(array->buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
length = njs_typed_array_length(array);
buffer = njs_buffer_alloc_array(vm, length, 0);
@@ -597,9 +602,9 @@ njs_buffer_array_range(njs_vm_t *vm, njs
const njs_value_t *start, const njs_value_t *end, const char *name,
uint8_t **out_start, uint8_t **out_end)
{
- uint8_t *u8;
- uint64_t num_start, num_end;
- njs_int_t ret;
+ uint64_t num_start, num_end;
+ njs_int_t ret;
+ njs_array_buffer_t *buffer;
num_start = 0;
@@ -633,9 +638,14 @@ njs_buffer_array_range(njs_vm_t *vm, njs
num_end = num_start;
}
- u8 = njs_typed_array_buffer(array)->u.u8;
- *out_start = &u8[array->offset + num_start];
- *out_end = &u8[array->offset + num_end];
+ buffer = njs_typed_array_buffer(array);
+ if (njs_slow_path(njs_is_detached_buffer(buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
+ *out_start = &buffer->u.u8[array->offset + num_start];
+ *out_end = &buffer->u.u8[array->offset + num_end];
return NJS_OK;
}
@@ -746,6 +756,10 @@ njs_buffer_concat(njs_vm_t *vm, njs_valu
}
arr = njs_typed_array(value);
+ if (njs_slow_path(njs_is_detached_buffer(arr->buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
if (njs_slow_path((SIZE_MAX - len) < arr->byte_length)) {
njs_type_error(vm, "Invalid length");
@@ -770,6 +784,10 @@ njs_buffer_concat(njs_vm_t *vm, njs_valu
}
arr = njs_typed_array(&retval);
+ if (njs_slow_path(njs_is_detached_buffer(arr->buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
if (njs_slow_path((SIZE_MAX - len) < arr->byte_length)) {
njs_type_error(vm, "Invalid length");
@@ -947,6 +965,11 @@ njs_buffer_prototype_read_int(njs_vm_t *
#endif
buffer = array->buffer;
+ if (njs_slow_path(njs_is_detached_buffer(buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
u8 = &buffer->u.u8[index + array->offset];
switch (size) {
@@ -1127,6 +1150,11 @@ njs_buffer_prototype_read_float(njs_vm_t
#endif
buffer = array->buffer;
+ if (njs_slow_path(njs_is_detached_buffer(buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
u8 = &buffer->u.u8[index + array->offset];
switch (size) {
@@ -1657,6 +1685,11 @@ njs_buffer_fill(njs_vm_t *vm, njs_typed_
return ret;
}
+ if (njs_slow_path(njs_is_detached_buffer(buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
memset(start, njs_number_to_uint32(num) & 0xff, end - offset);
}
@@ -1783,6 +1816,11 @@ njs_buffer_prototype_to_string(njs_vm_t
end = njs_min(end, array->byte_length);
}
+ if (njs_slow_path(njs_is_detached_buffer(array->buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
str.start = &njs_typed_array_buffer(array)->u.u8[array->offset + start];
str.length = end - start;
@@ -1890,12 +1928,14 @@ static njs_int_t
njs_buffer_prototype_index_of(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t last)
{
- uint8_t *u8, byte;
+ uint8_t byte;
int64_t from, to, increment, length, offset, index, i;
njs_int_t ret;
njs_str_t str;
njs_value_t *this, *value, *value_from, *enc, dst;
+ const uint8_t *u8;
njs_typed_array_t *array, *src;
+ njs_array_buffer_t *buffer;
const njs_buffer_encoding_t *encoding;
encoding = njs_buffer_utf8_encoding();
@@ -1977,7 +2017,13 @@ njs_buffer_prototype_index_of(njs_vm_t *
}
}
- u8 = &njs_typed_array_buffer(array)->u.u8[0];
+ buffer = njs_typed_array_buffer(array);
+ if (njs_slow_path(njs_is_detached_buffer(buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
+ u8 = &buffer->u.u8[0];
offset = array->offset;
switch (value->type) {
@@ -1997,6 +2043,11 @@ njs_buffer_prototype_index_of(njs_vm_t *
goto fail;
}
+ if (njs_slow_path(njs_is_detached_buffer(src->buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
str.start = &src->buffer->u.u8[src->offset];
str.length = src->byte_length;
}
@@ -2152,13 +2203,14 @@ static njs_int_t
njs_buffer_prototype_to_json(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused)
{
- u_char *p, *end;
- njs_int_t ret;
- njs_value_t *value;
- njs_value_t object, array;
- njs_array_t *arr;
- njs_object_t *obj;
- njs_typed_array_t *ta;
+ u_char *p, *end;
+ njs_int_t ret;
+ njs_value_t *value;
+ njs_value_t object, array;
+ njs_array_t *arr;
+ njs_object_t *obj;
+ njs_typed_array_t *ta;
+ njs_array_buffer_t *buffer;
static const njs_value_t string_buffer = njs_string("Buffer");
@@ -2185,7 +2237,13 @@ njs_buffer_prototype_to_json(njs_vm_t *v
return NJS_ERROR;
}
- p = &njs_typed_array_buffer(ta)->u.u8[ta->offset];
+ buffer = njs_typed_array_buffer(ta);
+ if (njs_slow_path(njs_is_detached_buffer(buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
+ p = &buffer->u.u8[ta->offset];
end = p + ta->byte_length;
value = arr->start;
diff -r 0cfc928cc1e4 -r f7f7994b69b5 src/njs_builtin.c
--- a/src/njs_builtin.c Thu Sep 17 13:10:51 2020 +0300
+++ b/src/njs_builtin.c Fri Sep 18 18:00:32 2020 +0000
@@ -35,6 +35,9 @@ static njs_int_t njs_env_hash_init(njs_v
static const njs_object_init_t njs_global_this_init;
static const njs_object_init_t njs_njs_object_init;
static const njs_object_init_t njs_process_object_init;
+#ifdef NJS_TEST262
+static const njs_object_init_t njs_262_object_init;
+#endif
static const njs_object_init_t *njs_object_init[] = {
@@ -43,6 +46,9 @@ static const njs_object_init_t *njs_obj
&njs_process_object_init,
&njs_math_object_init,
&njs_json_object_init,
+#ifdef NJS_TEST262
+ &njs_262_object_init,
+#endif
NULL
};
@@ -1259,6 +1265,18 @@ static const njs_object_prop_t njs_glob
.configurable = 1,
},
+#ifdef NJS_TEST262
+ {
+ .type = NJS_PROPERTY_HANDLER,
+ .name = njs_string("$262"),
+ .value = njs_prop_handler2(njs_top_level_object, NJS_OBJECT_262,
+ NJS_262_HASH),
+ .writable = 1,
+ .enumerable = 1,
+ .configurable = 1,
+ },
+#endif
+
/* Global constructors. */
{
@@ -1831,3 +1849,54 @@ static const njs_object_init_t njs_proc
njs_process_object_properties,
njs_nitems(njs_process_object_properties),
};
+
+
+#if (NJS_TEST262)
+
+static njs_int_t
+njs_262_detach_array_buffer(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
+ njs_index_t unused)
+{
+ njs_value_t *value;
+ njs_array_buffer_t *buffer;
+
+ value = njs_arg(args, nargs, 1);
+ if (njs_slow_path(!njs_is_array_buffer(value))) {
+ njs_type_error(vm, "\"this\" is not an ArrayBuffer");
+ return NJS_ERROR;
+ }
+
+ buffer = njs_array_buffer(value);
+ buffer->u.data = NULL;
+ buffer->size = 0;
+
+ njs_set_null(&vm->retval);
+
+ return NJS_OK;
+}
+
+static const njs_object_prop_t njs_262_object_properties[] =
+{
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_wellknown_symbol(NJS_SYMBOL_TO_STRING_TAG),
+ .value = njs_string("$262"),
+ .configurable = 1,
+ },
+
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_long_string("detachArrayBuffer"),
+ .value = njs_native_function(njs_262_detach_array_buffer, 2),
+ .writable = 1,
+ .configurable = 1,
+ },
+};
+
+
+static const njs_object_init_t njs_262_object_init = {
+ njs_262_object_properties,
+ njs_nitems(njs_262_object_properties),
+};
+
+#endif
diff -r 0cfc928cc1e4 -r f7f7994b69b5 src/njs_object_hash.h
--- a/src/njs_object_hash.h Thu Sep 17 13:10:51 2020 +0300
+++ b/src/njs_object_hash.h Fri Sep 18 18:00:32 2020 +0000
@@ -301,6 +301,14 @@
'n'), 'j'), 's')
+#define NJS_262_HASH \
+ njs_djb_hash_add( \
+ njs_djb_hash_add( \
+ njs_djb_hash_add( \
+ njs_djb_hash_add(NJS_DJB_HASH_INIT, \
+ '$'), '2'), '6'), '2')
+
+
#define NJS_NUMBER_HASH \
njs_djb_hash_add( \
njs_djb_hash_add( \
diff -r 0cfc928cc1e4 -r f7f7994b69b5 src/njs_typed_array.c
--- a/src/njs_typed_array.c Thu Sep 17 13:10:51 2020 +0300
+++ b/src/njs_typed_array.c Fri Sep 18 18:00:32 2020 +0000
@@ -64,7 +64,19 @@ njs_typed_array_alloc(njs_vm_t *vm, njs_
return NULL;
}
- if (!njs_is_undefined(njs_arg(args, nargs, 2))) {
+ if (njs_is_defined(njs_arg(args, nargs, 2))) {
+ ret = njs_value_to_index(vm, njs_argument(args, 2), &size);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return NULL;
+ }
+ }
+
+ if (njs_slow_path(njs_is_detached_buffer(buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NULL;
+ }
+
+ if (njs_is_defined(njs_arg(args, nargs, 2))) {
ret = njs_value_to_index(vm, njs_argument(args, 2), &size);
if (njs_slow_path(ret != NJS_OK)) {
return NULL;
@@ -95,6 +107,11 @@ njs_typed_array_alloc(njs_vm_t *vm, njs_
} else if (njs_is_typed_array(value)) {
src_tarray = njs_typed_array(value);
+ if (njs_slow_path(njs_is_detached_buffer(src_tarray->buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NULL;
+ }
+
size = (uint64_t) njs_typed_array_length(src_tarray) * element_size;
} else if (njs_is_object(value)) {
@@ -224,9 +241,10 @@ static njs_int_t
njs_typed_array_create(njs_vm_t *vm, njs_value_t *constructor,
njs_value_t *args, njs_uint_t nargs, njs_value_t *retval)
{
- njs_int_t ret;
- njs_value_t this;
- njs_object_t *object;
+ njs_int_t ret;
+ njs_value_t this;
+ njs_object_t *object;
+ njs_typed_array_t *array;
object = njs_function_new_object(vm, constructor);
if (njs_slow_path(object == NULL)) {
@@ -247,8 +265,14 @@ njs_typed_array_create(njs_vm_t *vm, njs
return NJS_ERROR;
}
+ array = njs_typed_array(retval);
+ if (njs_slow_path(njs_is_detached_buffer(array->buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
if (njs_slow_path(nargs == 1 && njs_is_number(&args[0])
- && njs_typed_array_length(njs_typed_array(retval))
+ && njs_typed_array_length(array)
< njs_number(&args[0])))
{
njs_type_error(vm, "Derived TypedArray constructor "
@@ -425,6 +449,10 @@ njs_typed_array_writable(njs_vm_t *vm, n
njs_array_buffer_t *buffer;
buffer = array->buffer;
+ if (njs_slow_path(njs_is_detached_buffer(buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NULL;
+ }
ret = njs_array_buffer_writable(vm, buffer);
if (njs_slow_path(ret != NJS_OK)) {
@@ -485,6 +513,7 @@ static njs_int_t
njs_typed_array_prototype_length(njs_vm_t *vm, njs_value_t *args,
njs_uint_t nargs, njs_index_t unused)
{
+ uint32_t length;
njs_value_t *this;
njs_typed_array_t *array;
@@ -496,8 +525,13 @@ njs_typed_array_prototype_length(njs_vm_
}
array = njs_typed_array(this);
-
- njs_set_number(&vm->retval, njs_typed_array_length(array));
+ length = njs_typed_array_length(array);
+
+ if (njs_slow_path(njs_is_detached_buffer(array->buffer))) {
+ length = 0;
+ }
+
+ njs_set_number(&vm->retval, length);
return NJS_OK;
}
@@ -529,6 +563,7 @@ static njs_int_t
njs_typed_array_prototype_byte_length(njs_vm_t *vm, njs_value_t *args,
njs_uint_t nargs, njs_index_t unused)
{
+ size_t byte_length;
njs_value_t *this;
njs_typed_array_t *array;
@@ -540,8 +575,18 @@ njs_typed_array_prototype_byte_length(nj
}
array = njs_typed_array(this);
-
- njs_set_number(&vm->retval, array->byte_length);
+ byte_length = array->byte_length;
+
+ if (njs_slow_path(njs_is_detached_buffer(array->buffer))) {
+ if (njs_is_data_view(this)) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
+ byte_length = 0;
+ }
+
+ njs_set_number(&vm->retval, byte_length);
return NJS_OK;
}
@@ -551,6 +596,7 @@ static njs_int_t
njs_typed_array_prototype_byte_offset(njs_vm_t *vm, njs_value_t *args,
njs_uint_t nargs, njs_index_t unused)
{
+ size_t byte_offset;
njs_value_t *this;
njs_typed_array_t *array;
@@ -562,8 +608,18 @@ njs_typed_array_prototype_byte_offset(nj
}
array = njs_typed_array(this);
-
- njs_set_number(&vm->retval, njs_typed_array_offset(array));
+ byte_offset = njs_typed_array_offset(array);
+
+ if (njs_slow_path(njs_is_detached_buffer(array->buffer))) {
+ if (njs_is_data_view(this)) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
+ byte_offset = 0;
+ }
+
+ njs_set_number(&vm->retval, byte_offset);
return NJS_OK;
}
@@ -693,6 +749,11 @@ njs_typed_array_prototype_set(njs_vm_t *
if (njs_is_typed_array(src)) {
src_tarray = njs_typed_array(src);
+ if (njs_slow_path(njs_is_detached_buffer(src_tarray->buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
src_length = njs_typed_array_length(src_tarray);
if (njs_slow_path((src_length > length)
@@ -767,6 +828,11 @@ njs_typed_array_prototype_set(njs_vm_t *
}
}
+ if (njs_slow_path(njs_is_detached_buffer(buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
njs_typed_array_prop_set(vm, self, offset + i, num);
}
}
@@ -803,6 +869,11 @@ njs_typed_array_prototype_fill(njs_vm_t
}
array = njs_typed_array(this);
+ if (njs_slow_path(njs_is_detached_buffer(array->buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
length = njs_typed_array_length(array);
setval = njs_lvalue_arg(&lvalue, args, nargs, 1);
@@ -929,6 +1000,10 @@ njs_typed_array_prototype_slice(njs_vm_t
array = njs_typed_array(this);
length = njs_typed_array_length(array);
buffer = njs_typed_array_buffer(array);
+ if (njs_slow_path(copy && njs_is_detached_buffer(buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
ret = njs_value_to_integer(vm, njs_arg(args, nargs, 1), &start);
if (njs_slow_path(ret != NJS_OK)) {
@@ -966,13 +1041,16 @@ njs_typed_array_prototype_slice(njs_vm_t
return ret;
}
- new_array = njs_typed_array(&vm->retval);
- if (njs_typed_array_length(new_array) < count) {
- njs_type_error(vm, "Derived TypedArray constructor is "
- "too small array");
+ if (count == 0) {
+ return NJS_OK;
+ }
+
+ if (njs_slow_path(njs_is_detached_buffer(buffer))) {
+ njs_type_error(vm, "detached buffer");
return NJS_ERROR;
}
+ new_array = njs_typed_array(&vm->retval);
new_buffer = njs_typed_array_buffer(new_array);
element_size = njs_typed_array_element_size(array->type);
@@ -1022,6 +1100,11 @@ njs_typed_array_prototype_copy_within(nj
}
array = njs_typed_array(this);
+ if (njs_slow_path(njs_is_detached_buffer(array->buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
length = njs_typed_array_length(array);
value = njs_arg(args, nargs, 1);
@@ -1044,10 +1127,9 @@ njs_typed_array_prototype_copy_within(nj
value = njs_arg(args, nargs, 3);
- if (njs_is_undefined(value)) {
- final = length;
-
- } else {
+ final = length;
+
+ if (njs_is_defined(value)) {
ret = njs_value_to_integer(vm, value, &final);
if (njs_slow_path(ret != NJS_OK)) {
return NJS_ERROR;
@@ -1085,14 +1167,15 @@ static njs_int_t
njs_typed_array_prototype_iterator(njs_vm_t *vm, njs_value_t *args,
njs_uint_t nargs, njs_index_t type)
{
- double val;
- int64_t i, length;
- njs_int_t ret;
- njs_arr_t results;
- njs_value_t *this, *this_arg, *r;
- njs_value_t arguments[4], retval;
- njs_function_t *function;
- njs_typed_array_t *array, *dst;
+ double val;
+ int64_t i, length;
+ njs_int_t ret;
+ njs_arr_t results;
+ njs_value_t *this, *this_arg, *r;
+ njs_value_t arguments[4], retval;
+ njs_function_t *function;
+ njs_typed_array_t *array, *dst;
+ njs_array_buffer_t *buffer;
this = njs_argument(args, 0);
if (njs_slow_path(!njs_is_typed_array(this))) {
@@ -1112,6 +1195,7 @@ njs_typed_array_prototype_iterator(njs_v
function = njs_function(njs_argument(args, 1));
this_arg = njs_arg(args, nargs, 2);
+ buffer = array->buffer;
results.separate = 0;
results.pointer = 0;
@@ -1136,6 +1220,11 @@ njs_typed_array_prototype_iterator(njs_v
}
for (i = 0; i < length; i++) {
+ if (njs_slow_path(njs_is_detached_buffer(buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
val = njs_typed_array_prop(array, i);
arguments[0] = *this_arg;
@@ -1349,6 +1438,11 @@ njs_typed_array_prototype_index_of(njs_v
}
}
+ if (njs_slow_path(njs_is_detached_buffer(array->buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
v = njs_number(njs_argument(args, 1));
i64 = v;
@@ -1491,12 +1585,13 @@ static njs_int_t
njs_typed_array_prototype_reduce(njs_vm_t *vm, njs_value_t *args,
njs_uint_t nargs, njs_index_t right)
{
- int64_t i, from, to, increment, length;
- njs_int_t ret;
- njs_value_t *this, accumulator;
- njs_value_t arguments[5];
- njs_function_t *function;
- njs_typed_array_t *array;
+ int64_t i, from, to, increment, length;
+ njs_int_t ret;
+ njs_value_t *this, accumulator;
+ njs_value_t arguments[5];
+ njs_function_t *function;
+ njs_typed_array_t *array;
+ njs_array_buffer_t *buffer;
this = njs_argument(args, 0);
if (njs_slow_path(!njs_is_typed_array(this))) {
@@ -1530,15 +1625,27 @@ njs_typed_array_prototype_reduce(njs_vm_
increment = 1;
}
+ buffer = array->buffer;
+
if (nargs > 2) {
accumulator = *njs_argument(args, 2);
} else {
+ if (njs_slow_path(njs_is_detached_buffer(buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
njs_set_number(&accumulator, njs_typed_array_prop(array, from));
from += increment;
}
for (i = from; i != to; i += increment) {
+ if (njs_slow_path(njs_is_detached_buffer(buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
njs_set_undefined(&arguments[0]);
arguments[1] = accumulator;
njs_set_number(&arguments[2], njs_typed_array_prop(array, i));
@@ -1785,6 +1892,7 @@ njs_typed_array_get_f64(const void *a)
typedef struct {
njs_vm_t *vm;
+ njs_array_buffer_t *buffer;
njs_function_t *function;
njs_bool_t exception;
double (*get)(const void *v);
@@ -1821,6 +1929,11 @@ njs_typed_array_generic_compare(const vo
goto exception;
}
+ if (njs_slow_path(njs_is_detached_buffer(ctx->buffer))) {
+ njs_type_error(ctx->vm, "detached buffer");
+ goto exception;
+ }
+
if (njs_slow_path(isnan(num))) {
return 0;
}
@@ -1858,7 +1971,14 @@ njs_typed_array_prototype_sort(njs_vm_t
return NJS_ERROR;
}
+ array = njs_typed_array(this);
+ if (njs_slow_path(njs_is_detached_buffer(array->buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
ctx.vm = vm;
+ ctx.buffer = array->buffer;
ctx.exception = 0;
comparefn = njs_arg(args, nargs, 1);
@@ -1875,8 +1995,6 @@ njs_typed_array_prototype_sort(njs_vm_t
ctx.function = NULL;
}
- array = njs_typed_array(this);
-
switch (array->type) {
case NJS_OBJ_TYPE_UINT8_ARRAY:
case NJS_OBJ_TYPE_UINT8_CLAMPED_ARRAY:
@@ -2022,6 +2140,11 @@ njs_typed_array_prototype_join(njs_vm_t
}
array = njs_typed_array(this);
+ if (njs_slow_path(njs_is_detached_buffer(array->buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
arr_length = njs_typed_array_length(array);
separator = njs_arg(args, nargs, 1);
@@ -2406,13 +2529,17 @@ njs_data_view_constructor(njs_vm_t *vm,
size = 0;
offset = 0;
- buffer = njs_array_buffer(njs_argument(args, 1));
-
ret = njs_value_to_index(vm, njs_arg(args, nargs, 2), &offset);
if (njs_slow_path(ret != NJS_OK)) {
return NJS_ERROR;
}
+ buffer = njs_array_buffer(njs_argument(args, 1));
+ if (njs_slow_path(njs_is_detached_buffer(buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
if (!njs_is_undefined(njs_arg(args, nargs, 3))) {
ret = njs_value_to_index(vm, njs_argument(args, 3), &size);
if (njs_slow_path(ret != NJS_OK)) {
@@ -2526,6 +2653,10 @@ njs_data_view_prototype_get(njs_vm_t *vm
#endif
view = njs_data_view(this);
+ if (njs_slow_path(njs_is_detached_buffer(view->buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
if (njs_typed_array_element_size(type) + index > view->byte_length) {
njs_range_error(vm, "index %uL is outside the bound of the buffer",
@@ -2647,6 +2778,10 @@ njs_data_view_prototype_set(njs_vm_t *vm
#endif
view = njs_data_view(this);
+ if (njs_slow_path(njs_is_detached_buffer(view->buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
if (njs_typed_array_element_size(type) + index > view->byte_length) {
njs_range_error(vm, "index %uL is outside the bound of the buffer",
diff -r 0cfc928cc1e4 -r f7f7994b69b5 src/njs_value.c
--- a/src/njs_value.c Thu Sep 17 13:10:51 2020 +0300
+++ b/src/njs_value.c Fri Sep 18 18:00:32 2020 +0000
@@ -807,6 +807,11 @@ njs_typed_array_property_query(njs_vm_t
{
njs_object_prop_t *prop;
+ if (njs_slow_path(njs_is_detached_buffer(array->buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
if (index >= njs_typed_array_length(array)) {
return NJS_DECLINED;
}
@@ -959,6 +964,11 @@ njs_value_property(njs_vm_t *vm, njs_val
if (njs_is_typed_array(value)) {
tarray = njs_typed_array(value);
+ if (njs_slow_path(njs_is_detached_buffer(tarray->buffer))) {
+ njs_type_error(vm, "detached buffer");
+ return NJS_ERROR;
+ }
+
if (njs_slow_path(index >= njs_typed_array_length(tarray))) {
goto slow_path;
}
diff -r 0cfc928cc1e4 -r f7f7994b69b5 src/njs_value.h
--- a/src/njs_value.h Thu Sep 17 13:10:51 2020 +0300
+++ b/src/njs_value.h Fri Sep 18 18:00:32 2020 +0000
@@ -659,6 +659,10 @@ typedef struct {
((value)->type == NJS_TYPED_ARRAY)
+#define njs_is_detached_buffer(buffer) \
+ ((buffer)->u.data == NULL)
+
+
#define njs_is_data_view(value) \
((value)->type == NJS_DATA_VIEW)
diff -r 0cfc928cc1e4 -r f7f7994b69b5 src/njs_vm.h
--- a/src/njs_vm.h Thu Sep 17 13:10:51 2020 +0300
+++ b/src/njs_vm.h Fri Sep 18 18:00:32 2020 +0000
@@ -140,7 +140,10 @@ enum njs_object_e {
NJS_OBJECT_PROCESS,
NJS_OBJECT_MATH,
NJS_OBJECT_JSON,
-#define NJS_OBJECT_MAX (NJS_OBJECT_JSON + 1)
+#ifdef NJS_TEST262
+ NJS_OBJECT_262,
+#endif
+ NJS_OBJECT_MAX
};
diff -r 0cfc928cc1e4 -r f7f7994b69b5 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c Thu Sep 17 13:10:51 2020 +0300
+++ b/src/test/njs_unit_test.c Fri Sep 18 18:00:32 2020 +0000
@@ -19578,7 +19578,11 @@ static njs_unit_test_t njs_externals_te
njs_str("true") },
{ njs_str("Object.keys(this).sort()"),
+#if (NJS_TEST262)
+ njs_str("$262,$r,$r2,$r3,$shared,global,njs,process") },
+#else
njs_str("$r,$r2,$r3,$shared,global,njs,process") },
+#endif
{ njs_str("Object.getOwnPropertySymbols($r2)[0] == Symbol.toStringTag"),
njs_str("true") },
More information about the nginx-devel
mailing list