From: Dmitry Volyntsev Date: Fri, 18 Sep 2020 18:00:32 +0000 (+0000) Subject: Added support for detached-buffers. X-Git-Tag: 0.4.4~6 X-Git-Url: http://git.kaiwu.me/postgresql/log/contrib/postgres_fdw/%7B@url%7D?a=commitdiff_plain;h=2f3bc63175b30136157008eb1203ad23068b184c;p=njs.git Added support for detached-buffers. --- diff --git a/auto/cc b/auto/cc index 02c04a7f..5975757c 100644 --- a/auto/cc +++ b/auto/cc @@ -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 --git a/auto/help b/auto/help index ac20f7b3..ebffaf20 100644 --- a/auto/help +++ b/auto/help @@ -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 --git a/auto/options b/auto/options index 021f7357..89bcd3b4 100644 --- a/auto/options +++ b/auto/options @@ -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 --git a/src/njs_array_buffer.c b/src/njs_array_buffer.c index 8c09012f..b21235b5 100644 --- a/src/njs_array_buffer.c +++ b/src/njs_array_buffer.c @@ -204,6 +204,10 @@ njs_array_buffer_prototype_byte_length(njs_vm_t *vm, njs_value_t *args, } 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 --git a/src/njs_buffer.c b/src/njs_buffer.c index 459f62ef..d71fa1dd 100644 --- a/src/njs_buffer.c +++ b/src/njs_buffer.c @@ -441,6 +441,11 @@ njs_buffer_from_typed_array(njs_vm_t *vm, njs_value_t *value) 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_typed_array_t *array, 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_typed_array_t *array, 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_value_t *args, njs_uint_t nargs, } 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_value_t *args, njs_uint_t nargs, } 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 *vm, njs_value_t *args, njs_uint_t nargs, #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 *vm, njs_value_t *args, #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_array_t *array, njs_value_t *value, 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 *vm, njs_value_t *args, 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 *vm, njs_value_t *args, njs_uint_t nargs, } } - 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 *vm, njs_value_t *args, njs_uint_t nargs, 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 *vm, njs_value_t *args, njs_uint_t nargs, 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 --git a/src/njs_builtin.c b/src/njs_builtin.c index 62947ebc..252796d3 100644 --- a/src/njs_builtin.c +++ b/src/njs_builtin.c @@ -35,6 +35,9 @@ static njs_int_t njs_env_hash_init(njs_vm_t *vm, njs_lvlhsh_t *hash, 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_object_init[] = { &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_global_this_object_properties[] = .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_process_object_init = { 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 --git a/src/njs_object_hash.h b/src/njs_object_hash.h index db2ef7fa..a5cc0210 100644 --- a/src/njs_object_hash.h +++ b/src/njs_object_hash.h @@ -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 --git a/src/njs_typed_array.c b/src/njs_typed_array.c index accfb77e..c74fbf03 100644 --- a/src/njs_typed_array.c +++ b/src/njs_typed_array.c @@ -64,7 +64,19 @@ njs_typed_array_alloc(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, 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_value_t *args, njs_uint_t nargs, } 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_value_t *constructor, 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, njs_typed_array_t *array) 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_t *vm, njs_value_t *args, } array = njs_typed_array(this); + length = njs_typed_array_length(array); - njs_set_number(&vm->retval, 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(njs_vm_t *vm, njs_value_t *args, } array = njs_typed_array(this); + byte_length = array->byte_length; - njs_set_number(&vm->retval, 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(njs_vm_t *vm, njs_value_t *args, } array = njs_typed_array(this); + 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, njs_typed_array_offset(array)); + njs_set_number(&vm->retval, byte_offset); return NJS_OK; } @@ -693,6 +749,11 @@ njs_typed_array_prototype_set(njs_vm_t *vm, njs_value_t *args, 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 *vm, njs_value_t *args, } } + 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 *vm, njs_value_t *args, } 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 *vm, njs_value_t *args, 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 *vm, njs_value_t *args, 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(njs_vm_t *vm, njs_value_t *args, } 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(njs_vm_t *vm, njs_value_t *args, value = njs_arg(args, nargs, 3); - if (njs_is_undefined(value)) { - final = length; + final = length; - } else { + 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_vm_t *vm, njs_value_t *args, 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_vm_t *vm, njs_value_t *args, } 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_vm_t *vm, njs_value_t *args, } } + 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_t *vm, njs_value_t *args, 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 void *a, const void *b, void *c) 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 *vm, njs_value_t *args, 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 *vm, njs_value_t *args, 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 *vm, njs_value_t *args, } 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, njs_value_t *args, njs_uint_t nargs, 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, njs_value_t *args, #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, njs_value_t *args, #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 --git a/src/njs_value.c b/src/njs_value.c index b2c2ad97..5cd78d7f 100644 --- a/src/njs_value.c +++ b/src/njs_value.c @@ -807,6 +807,11 @@ njs_typed_array_property_query(njs_vm_t *vm, njs_property_query_t *pq, { 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_value_t *value, njs_value_t *key, 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 --git a/src/njs_value.h b/src/njs_value.h index 967dcb5d..1cf808a1 100644 --- a/src/njs_value.h +++ b/src/njs_value.h @@ -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 --git a/src/njs_vm.h b/src/njs_vm.h index 02789e9a..7a77b311 100644 --- a/src/njs_vm.h +++ b/src/njs_vm.h @@ -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 --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index 6b4b766b..250f20c9 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -19578,7 +19578,11 @@ static njs_unit_test_t njs_externals_test[] = 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") },