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.
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 \
}
}
- if (njs_is_string(name)) {
- flags |= NJS_OBJECT_PROP_IS_STRING;
- }
-
return njs_object_prop_define(vm, object, name->atom_id, value, flags);
}
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;
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)) {
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;
}
"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]; }});"