[runtime] Fix TypedArrayPrototype protector cell checks

Previously, we were looking up the prototype of the receiver and
checking that against %TypedArrayPrototype% before invalidating the
protector cell.

This is incorrect as it's possible to patch the prototype and then
change the constructor property, bypassing this check.

This CL adds a new instance type to prototype of all TypedArray
constructors and checks the receiver against this instance type.

TBR: tebbi@chromium.org
Bug: v8:11274, v8:11256
Change-Id: I2ff6280e4cf820b06c5593fe4addd36f7ac656c4
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2594776
Commit-Queue: Sathya Gunasekaran  <gsathya@chromium.org>
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71799}
This commit is contained in:
Sathya Gunasekaran 2020-12-16 15:41:50 +00:00 committed by Commit Bot
parent 62355eeb2c
commit 15c227befb
14 changed files with 88 additions and 56 deletions

View File

@ -149,6 +149,9 @@ extern class JSRegExpPrototype extends JSPrototype
extern class JSPromisePrototype extends JSPrototype
generates 'TNode<JSObject>';
@doNotGenerateCast
extern class JSTypedArrayPrototype extends JSPrototype
generates 'TNode<JSObject>';
@doNotGenerateCast
extern class JSSetPrototype extends JSPrototype
generates 'TNode<JSObject>';
@doNotGenerateCast

View File

@ -198,6 +198,7 @@ Type::bitset BitsetType::Lub(const MapRefLike& map) {
case JS_GLOBAL_PROXY_TYPE:
case JS_API_OBJECT_TYPE:
case JS_SPECIAL_API_OBJECT_TYPE:
case JS_TYPED_ARRAY_PROTOTYPE_TYPE:
if (map.is_undetectable()) {
// Currently we assume that every undetectable receiver is also
// callable, which is what we need to support document.all. We

View File

@ -228,6 +228,7 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) {
case JS_SET_PROTOTYPE_TYPE:
case JS_SPECIAL_API_OBJECT_TYPE:
case JS_STRING_ITERATOR_PROTOTYPE_TYPE:
case JS_TYPED_ARRAY_PROTOTYPE_TYPE:
JSObject::cast(*this).JSObjectVerify(isolate);
break;
case WASM_INSTANCE_OBJECT_TYPE:

View File

@ -173,6 +173,7 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
case JS_SET_PROTOTYPE_TYPE:
case JS_SPECIAL_API_OBJECT_TYPE:
case JS_STRING_ITERATOR_PROTOTYPE_TYPE:
case JS_TYPED_ARRAY_PROTOTYPE_TYPE:
JSObject::cast(*this).JSObjectPrint(os);
break;
case WASM_INSTANCE_OBJECT_TYPE:

View File

@ -4044,6 +4044,10 @@ Handle<JSFunction> Genesis::InstallTypedArray(const char* name,
kDontThrow)
.FromJust());
CHECK_NE(prototype->map().ptr(),
isolate_->initial_object_prototype()->map().ptr());
prototype->map().set_instance_type(JS_TYPED_ARRAY_PROTOTYPE_TYPE);
InstallConstant(isolate(), prototype, "BYTES_PER_ELEMENT", bytes_per_element);
return result;
}

View File

@ -520,6 +520,7 @@ bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
case JS_SET_ITERATOR_PROTOTYPE_TYPE:
case JS_SET_PROTOTYPE_TYPE:
case JS_STRING_ITERATOR_PROTOTYPE_TYPE:
case JS_TYPED_ARRAY_PROTOTYPE_TYPE:
#ifdef V8_INTL_SUPPORT
case JS_COLLATOR_TYPE:
case JS_DATE_TIME_FORMAT_TYPE:

View File

@ -2185,6 +2185,7 @@ int JSObject::GetHeaderSize(InstanceType type,
case JS_SPECIAL_API_OBJECT_TYPE:
case JS_STRING_ITERATOR_PROTOTYPE_TYPE:
case JS_ARRAY_ITERATOR_PROTOTYPE_TYPE:
case JS_TYPED_ARRAY_PROTOTYPE_TYPE:
return JSObject::kHeaderSize;
case JS_GENERATOR_OBJECT_TYPE:
return JSGeneratorObject::kHeaderSize;

View File

@ -234,9 +234,6 @@ void LookupIterator::InternalUpdateProtector(Isolate* isolate,
DisallowGarbageCollection no_gc;
// Setting the constructor of any prototype with the @@species protector
// (of any realm) also needs to invalidate the protector.
// For typed arrays, we check a prototype of this receiver since
// TypedArrays have different prototypes for each type, and their parent
// prototype is pointing the same TYPED_ARRAY_PROTOTYPE.
if (isolate->IsInAnyContext(*receiver,
Context::INITIAL_ARRAY_PROTOTYPE_INDEX)) {
if (!Protectors::IsArraySpeciesLookupChainIntact(isolate)) return;
@ -251,9 +248,7 @@ void LookupIterator::InternalUpdateProtector(Isolate* isolate,
Context::REGEXP_PROTOTYPE_INDEX)) {
if (!Protectors::IsRegExpSpeciesLookupChainIntact(isolate)) return;
Protectors::InvalidateRegExpSpeciesLookupChain(isolate);
} else if (isolate->IsInAnyContext(
receiver->map(isolate).prototype(isolate),
Context::TYPED_ARRAY_PROTOTYPE_INDEX)) {
} else if (receiver->IsJSTypedArrayPrototype()) {
if (!Protectors::IsTypedArraySpeciesLookupChainIntact(isolate)) return;
Protectors::InvalidateTypedArraySpeciesLookupChain(isolate);
}

View File

@ -283,6 +283,7 @@ VisitorId Map::GetVisitorId(Map map) {
case JS_SET_VALUE_ITERATOR_TYPE:
case JS_STRING_ITERATOR_PROTOTYPE_TYPE:
case JS_STRING_ITERATOR_TYPE:
case JS_TYPED_ARRAY_PROTOTYPE_TYPE:
#ifdef V8_INTL_SUPPORT
case JS_V8_BREAK_ITERATOR_TYPE:
case JS_COLLATOR_TYPE:

View File

@ -283,6 +283,7 @@ class ZoneForwardList;
V(JSIteratorPrototype) \
V(JSArrayIteratorPrototype) \
V(JSMapIteratorPrototype) \
V(JSTypedArrayPrototype) \
V(JSSetIteratorPrototype) \
V(JSStringIteratorPrototype)

View File

@ -975,6 +975,7 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
case JS_SPECIAL_API_OBJECT_TYPE:
case JS_STRING_ITERATOR_PROTOTYPE_TYPE:
case JS_STRING_ITERATOR_TYPE:
case JS_TYPED_ARRAY_PROTOTYPE_TYPE:
#ifdef V8_INTL_SUPPORT
case JS_V8_BREAK_ITERATOR_TYPE:
case JS_COLLATOR_TYPE:

View File

@ -540,6 +540,7 @@ Maybe<bool> ValueSerializer::WriteJSReceiver(Handle<JSReceiver> receiver) {
case JS_SET_ITERATOR_PROTOTYPE_TYPE:
case JS_SET_PROTOTYPE_TYPE:
case JS_STRING_ITERATOR_PROTOTYPE_TYPE:
case JS_TYPED_ARRAY_PROTOTYPE_TYPE:
case JS_API_OBJECT_TYPE: {
Handle<JSObject> js_object = Handle<JSObject>::cast(receiver);
if (JSObject::GetEmbedderFieldCount(js_object->map())) {

View File

@ -0,0 +1,20 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
var typedArrayProto = Uint8Array.prototype.__proto__;
var typedArrayConstructor = Uint8Array.prototype.constructor[Symbol.species];
var called = false;
Uint8Array.prototype.__proto__ = {};
Uint8Array.prototype.constructor = {
get [Symbol.species]() {
called = true;
return typedArrayConstructor;
}
}
Uint8Array.prototype.__proto__ = typedArrayProto;
var arr = new Uint8Array(8);
arr.slice(1, 5);
assertTrue(called);

View File

@ -162,56 +162,57 @@ INSTANCE_TYPES = {
1048: "JS_SET_ITERATOR_PROTOTYPE_TYPE",
1049: "JS_SET_PROTOTYPE_TYPE",
1050: "JS_STRING_ITERATOR_PROTOTYPE_TYPE",
1051: "JS_MAP_KEY_ITERATOR_TYPE",
1052: "JS_MAP_KEY_VALUE_ITERATOR_TYPE",
1053: "JS_MAP_VALUE_ITERATOR_TYPE",
1054: "JS_SET_KEY_VALUE_ITERATOR_TYPE",
1055: "JS_SET_VALUE_ITERATOR_TYPE",
1051: "JS_TYPED_ARRAY_PROTOTYPE_TYPE",
1052: "JS_GENERATOR_OBJECT_TYPE",
1053: "JS_ASYNC_FUNCTION_OBJECT_TYPE",
1054: "JS_ASYNC_GENERATOR_OBJECT_TYPE",
1055: "JS_ARGUMENTS_OBJECT_TYPE",
1056: "JS_API_OBJECT_TYPE",
1058: "JS_GENERATOR_OBJECT_TYPE",
1059: "JS_ASYNC_FUNCTION_OBJECT_TYPE",
1060: "JS_ASYNC_GENERATOR_OBJECT_TYPE",
1061: "JS_DATA_VIEW_TYPE",
1062: "JS_TYPED_ARRAY_TYPE",
1063: "JS_MAP_TYPE",
1064: "JS_SET_TYPE",
1065: "JS_WEAK_MAP_TYPE",
1066: "JS_WEAK_SET_TYPE",
1067: "JS_ARGUMENTS_OBJECT_TYPE",
1068: "JS_ARRAY_TYPE",
1069: "JS_ARRAY_BUFFER_TYPE",
1070: "JS_ARRAY_ITERATOR_TYPE",
1071: "JS_ASYNC_FROM_SYNC_ITERATOR_TYPE",
1072: "JS_COLLATOR_TYPE",
1073: "JS_CONTEXT_EXTENSION_OBJECT_TYPE",
1074: "JS_DATE_TYPE",
1075: "JS_DATE_TIME_FORMAT_TYPE",
1076: "JS_DISPLAY_NAMES_TYPE",
1077: "JS_ERROR_TYPE",
1078: "JS_FINALIZATION_REGISTRY_TYPE",
1079: "JS_LIST_FORMAT_TYPE",
1080: "JS_LOCALE_TYPE",
1081: "JS_MESSAGE_OBJECT_TYPE",
1082: "JS_NUMBER_FORMAT_TYPE",
1083: "JS_PLURAL_RULES_TYPE",
1084: "JS_PROMISE_TYPE",
1085: "JS_REG_EXP_TYPE",
1086: "JS_REG_EXP_STRING_ITERATOR_TYPE",
1087: "JS_RELATIVE_TIME_FORMAT_TYPE",
1088: "JS_SEGMENT_ITERATOR_TYPE",
1089: "JS_SEGMENTER_TYPE",
1090: "JS_SEGMENTS_TYPE",
1091: "JS_STRING_ITERATOR_TYPE",
1092: "JS_V8_BREAK_ITERATOR_TYPE",
1093: "JS_WEAK_REF_TYPE",
1094: "WASM_EXCEPTION_OBJECT_TYPE",
1095: "WASM_GLOBAL_OBJECT_TYPE",
1096: "WASM_INSTANCE_OBJECT_TYPE",
1097: "WASM_MEMORY_OBJECT_TYPE",
1098: "WASM_MODULE_OBJECT_TYPE",
1099: "WASM_TABLE_OBJECT_TYPE",
1100: "JS_BOUND_FUNCTION_TYPE",
1101: "JS_FUNCTION_TYPE",
1058: "JS_MAP_KEY_ITERATOR_TYPE",
1059: "JS_MAP_KEY_VALUE_ITERATOR_TYPE",
1060: "JS_MAP_VALUE_ITERATOR_TYPE",
1061: "JS_SET_KEY_VALUE_ITERATOR_TYPE",
1062: "JS_SET_VALUE_ITERATOR_TYPE",
1063: "JS_DATA_VIEW_TYPE",
1064: "JS_TYPED_ARRAY_TYPE",
1065: "JS_MAP_TYPE",
1066: "JS_SET_TYPE",
1067: "JS_WEAK_MAP_TYPE",
1068: "JS_WEAK_SET_TYPE",
1069: "JS_ARRAY_TYPE",
1070: "JS_ARRAY_BUFFER_TYPE",
1071: "JS_ARRAY_ITERATOR_TYPE",
1072: "JS_ASYNC_FROM_SYNC_ITERATOR_TYPE",
1073: "JS_COLLATOR_TYPE",
1074: "JS_CONTEXT_EXTENSION_OBJECT_TYPE",
1075: "JS_DATE_TYPE",
1076: "JS_DATE_TIME_FORMAT_TYPE",
1077: "JS_DISPLAY_NAMES_TYPE",
1078: "JS_ERROR_TYPE",
1079: "JS_FINALIZATION_REGISTRY_TYPE",
1080: "JS_LIST_FORMAT_TYPE",
1081: "JS_LOCALE_TYPE",
1082: "JS_MESSAGE_OBJECT_TYPE",
1083: "JS_NUMBER_FORMAT_TYPE",
1084: "JS_PLURAL_RULES_TYPE",
1085: "JS_PROMISE_TYPE",
1086: "JS_REG_EXP_TYPE",
1087: "JS_REG_EXP_STRING_ITERATOR_TYPE",
1088: "JS_RELATIVE_TIME_FORMAT_TYPE",
1089: "JS_SEGMENT_ITERATOR_TYPE",
1090: "JS_SEGMENTER_TYPE",
1091: "JS_SEGMENTS_TYPE",
1092: "JS_STRING_ITERATOR_TYPE",
1093: "JS_V8_BREAK_ITERATOR_TYPE",
1094: "JS_WEAK_REF_TYPE",
1095: "WASM_EXCEPTION_OBJECT_TYPE",
1096: "WASM_GLOBAL_OBJECT_TYPE",
1097: "WASM_INSTANCE_OBJECT_TYPE",
1098: "WASM_MEMORY_OBJECT_TYPE",
1099: "WASM_MODULE_OBJECT_TYPE",
1100: "WASM_TABLE_OBJECT_TYPE",
1101: "JS_BOUND_FUNCTION_TYPE",
1102: "JS_FUNCTION_TYPE",
}
# List of known V8 maps.
@ -369,7 +370,7 @@ KNOWN_MAPS = {
("read_only_space", 0x05d2d): (78, "StoreHandler2Map"),
("read_only_space", 0x05d55): (78, "StoreHandler3Map"),
("map_space", 0x02115): (1057, "ExternalMap"),
("map_space", 0x0213d): (1081, "JSMessageObjectMap"),
("map_space", 0x0213d): (1082, "JSMessageObjectMap"),
("map_space", 0x02165): (182, "WasmRttEqrefMap"),
("map_space", 0x0218d): (182, "WasmRttAnyrefMap"),
("map_space", 0x021b5): (182, "WasmRttExternrefMap"),