From: Dmitry Volyntsev Date: Fri, 4 Sep 2026 01:48:39 +0000 (-0700) Subject: TypedArray: fix numeric property definitions X-Git-Tag: 1.0.2~74 X-Git-Url: https://git.kaiwu.me/%7B@url%7D?a=commitdiff_plain;h=7e4194c53303d222bdc77d0d742a71be298b8cf8;p=njs.git TypedArray: fix numeric property definitions Previously, integer-indexed exotic validation was restricted to keys marked as strings. Numeric atoms and the canonical string "NaN" could bypass the check and be installed as ordinary typed-array properties. The fix is to validate numeric atoms and canonical numeric strings after key conversion, and to remove the obsolete source-type flag. The numeric-key bypass was introduced in b28e50b1 (0.9.0); the incomplete canonical-index handling dates to bf208048 (0.3.8). This closes #1098 issue on GitHub. --- diff --git a/src/njs_object.h b/src/njs_object.h index 814964aa..319de1db 100644 --- a/src/njs_object.h +++ b/src/njs_object.h @@ -19,7 +19,6 @@ typedef enum { NJS_OBJECT_PROP_CONFIGURABLE = 16, NJS_OBJECT_PROP_WRITABLE = 32, NJS_OBJECT_PROP_UNSET = 64, - NJS_OBJECT_PROP_IS_STRING = 128, #define NJS_OBJECT_PROP_VALUE_ECW (NJS_OBJECT_PROP_VALUE \ | NJS_OBJECT_PROP_ENUMERABLE \ | NJS_OBJECT_PROP_CONFIGURABLE \ @@ -264,10 +263,6 @@ njs_object_prop_define_val(njs_vm_t *vm, njs_value_t *object, njs_value_t *name, } } - if (njs_is_string(name)) { - flags |= NJS_OBJECT_PROP_IS_STRING; - } - return njs_object_prop_define(vm, object, name->atom_id, value, flags); } diff --git a/src/njs_object_prop.c b/src/njs_object_prop.c index aaf8b683..6b3181d5 100644 --- a/src/njs_object_prop.c +++ b/src/njs_object_prop.c @@ -136,6 +136,7 @@ njs_object_prop_define(njs_vm_t *vm, njs_value_t *object, unsigned atom_id, uint32_t length, index, set_enumerable, set_configurable, set_writable; njs_int_t ret; + njs_str_t string; njs_array_t *array; njs_value_t key, retval; njs_object_prop_t _prop; @@ -220,22 +221,38 @@ set_prop: return NJS_ERROR; } - if (njs_slow_path(njs_is_typed_array(object) && - (flags & NJS_OBJECT_PROP_IS_STRING))) - { + if (njs_slow_path(njs_is_typed_array(object))) { /* Integer-Indexed Exotic Objects [[DefineOwnProperty]]. */ + if (njs_atom_is_number(atom_id)) { + index = njs_atom_number(atom_id); + + if (index < njs_typed_array_length(njs_typed_array(object))) { + goto complete; + } + + goto invalid_index; + } + ret = njs_atom_to_value(vm, &key, atom_id); if (njs_slow_path(ret != NJS_OK)) { return ret; } - if (!isnan(njs_string_to_index(&key))) { - njs_type_error(vm, "Invalid typed array index"); - return NJS_ERROR; + if (njs_is_string(&key)) { + njs_string_get(vm, &key, &string); + + if (!isnan(njs_string_to_index(&key)) + || (string.length == 3 + && memcmp(string.start, "NaN", 3) == 0)) + { + goto invalid_index; + } } } +complete: + /* 6.2.5.6 CompletePropertyDescriptor */ if (njs_is_accessor_descriptor(prop)) { @@ -559,6 +576,12 @@ exception: njs_atom_string_get(vm, atom_id, &pq.fhq.key); njs_type_error(vm, "Cannot redefine property: \"%V\"", &pq.fhq.key); + return NJS_ERROR; + +invalid_index: + + njs_type_error(vm, "Invalid typed array index"); + return NJS_ERROR; } diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index 2f4b080e..d1901825 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -7013,6 +7013,17 @@ static njs_unit_test_t njs_test[] = "Object.values(a); a[0]"), njs_str("2") }, + { njs_str("[257, '257', NaN, 'NaN', Infinity, 'Infinity', -0, '-0']" + ".every(k => { try {" + " Object.defineProperty(new Uint8Array(), k, {value: 1});" + "} catch (e) { return e.name == 'TypeError'; } })"), + njs_str("true") }, + + { njs_str("['01', ' 1', '0x10', '1e3'].every(k => {" + "var a = new Uint8Array();" + "Object.defineProperty(a, k, {value: 1}); return a[k] == 1; })"), + njs_str("true") }, + { njs_str("var a = Buffer.from([1]);" "Object.defineProperty(a, 'x', {enumerable: true," " get() { return this === a && this[0]; }});"