Skip to content

Commit 9c76633

Browse files
verwaestCommit Bot
authored and
Commit Bot
committed
Reland "[runtime] Fix protector invalidation"
This is a reland of e55e0aa Original change's description: > [runtime] Fix protector invalidation > > Protectors trigger when special properties are modified or masked. Previously > we would check whether the property stored on the holder would invalidate the > protector. Stores to to the receiver rather than the holder, however, so this > CL changes holder for receiver, and adds additional checks that were missing. > > Bug: v8:9466 > Change-Id: I81bc3d73f91381da0d254e9eb79365ae2d25d998 > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1708468 > Commit-Queue: Leszek Swirski <[email protected]> > Reviewed-by: Leszek Swirski <[email protected]> > Cr-Commit-Position: refs/heads/master@{#62805} Tbr: [email protected] Bug: v8:9466 Change-Id: I693c73577ca9a35a271f509770cc1c87e5cc4b73 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1709420 Commit-Queue: Toon Verwaest <[email protected]> Reviewed-by: Leszek Swirski <[email protected]> Reviewed-by: Sathya Gunasekaran <[email protected]> Cr-Commit-Position: refs/heads/master@{#62829}
1 parent 3e51c41 commit 9c76633

File tree

6 files changed

+68
-42
lines changed

6 files changed

+68
-42
lines changed

src/objects/lookup.cc

Lines changed: 54 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ void LookupIterator::ReloadPropertyInformation() {
212212

213213
namespace {
214214

215-
bool IsTypedArrayFunctionInAnyContext(Isolate* isolate, JSReceiver holder) {
215+
bool IsTypedArrayFunctionInAnyContext(Isolate* isolate, HeapObject object) {
216216
static uint32_t context_slots[] = {
217217
#define TYPED_ARRAY_CONTEXT_SLOTS(Type, type, TYPE, ctype) \
218218
Context::TYPE##_ARRAY_FUN_INDEX,
@@ -221,17 +221,19 @@ bool IsTypedArrayFunctionInAnyContext(Isolate* isolate, JSReceiver holder) {
221221
#undef TYPED_ARRAY_CONTEXT_SLOTS
222222
};
223223

224-
if (!holder.IsJSFunction(isolate)) return false;
224+
if (!object.IsJSFunction(isolate)) return false;
225225

226226
return std::any_of(
227227
std::begin(context_slots), std::end(context_slots),
228-
[=](uint32_t slot) { return isolate->IsInAnyContext(holder, slot); });
228+
[=](uint32_t slot) { return isolate->IsInAnyContext(object, slot); });
229229
}
230230

231231
} // namespace
232232

233233
void LookupIterator::InternalUpdateProtector() {
234234
if (isolate_->bootstrapper()->IsActive()) return;
235+
if (!receiver_->IsHeapObject()) return;
236+
Handle<HeapObject> receiver = Handle<HeapObject>::cast(receiver_);
235237

236238
Handle<NativeContext> native_context = isolate_->native_context();
237239

@@ -244,70 +246,74 @@ void LookupIterator::InternalUpdateProtector() {
244246
return;
245247
}
246248
// Setting the constructor property could change an instance's @@species
247-
if (holder_->IsJSArray(isolate_)) {
249+
if (receiver->IsJSArray(isolate_)) {
248250
if (!isolate_->IsArraySpeciesLookupChainIntact()) return;
249251
isolate_->CountUsage(
250252
v8::Isolate::UseCounterFeature::kArrayInstanceConstructorModified);
251253
isolate_->InvalidateArraySpeciesProtector();
252254
return;
253-
} else if (holder_->IsJSPromise(isolate_)) {
255+
} else if (receiver->IsJSPromise(isolate_)) {
254256
if (!isolate_->IsPromiseSpeciesLookupChainIntact()) return;
255257
isolate_->InvalidatePromiseSpeciesProtector();
256258
return;
257-
} else if (holder_->IsJSRegExp(isolate_)) {
259+
} else if (receiver->IsJSRegExp(isolate_)) {
258260
if (!isolate_->IsRegExpSpeciesLookupChainIntact(native_context)) return;
259261
isolate_->InvalidateRegExpSpeciesProtector(native_context);
260262
return;
261-
} else if (holder_->IsJSTypedArray(isolate_)) {
263+
} else if (receiver->IsJSTypedArray(isolate_)) {
262264
if (!isolate_->IsTypedArraySpeciesLookupChainIntact()) return;
263265
isolate_->InvalidateTypedArraySpeciesProtector();
264266
return;
265267
}
266-
if (holder_->map(isolate_).is_prototype_map()) {
268+
if (receiver->map(isolate_).is_prototype_map()) {
267269
DisallowHeapAllocation no_gc;
268270
// Setting the constructor of any prototype with the @@species protector
269271
// (of any realm) also needs to invalidate the protector.
270-
// For typed arrays, we check a prototype of this holder since TypedArrays
271-
// have different prototypes for each type, and their parent prototype is
272-
// pointing the same TYPED_ARRAY_PROTOTYPE.
273-
if (isolate_->IsInAnyContext(*holder_,
272+
// For typed arrays, we check a prototype of this receiver since
273+
// TypedArrays have different prototypes for each type, and their parent
274+
// prototype is pointing the same TYPED_ARRAY_PROTOTYPE.
275+
if (isolate_->IsInAnyContext(*receiver,
274276
Context::INITIAL_ARRAY_PROTOTYPE_INDEX)) {
275277
if (!isolate_->IsArraySpeciesLookupChainIntact()) return;
276278
isolate_->CountUsage(
277279
v8::Isolate::UseCounterFeature::kArrayPrototypeConstructorModified);
278280
isolate_->InvalidateArraySpeciesProtector();
279-
} else if (isolate_->IsInAnyContext(*holder_,
281+
} else if (isolate_->IsInAnyContext(*receiver,
280282
Context::PROMISE_PROTOTYPE_INDEX)) {
281283
if (!isolate_->IsPromiseSpeciesLookupChainIntact()) return;
282284
isolate_->InvalidatePromiseSpeciesProtector();
283-
} else if (isolate_->IsInAnyContext(*holder_,
285+
} else if (isolate_->IsInAnyContext(*receiver,
284286
Context::REGEXP_PROTOTYPE_INDEX)) {
285287
if (!isolate_->IsRegExpSpeciesLookupChainIntact(native_context)) return;
286288
isolate_->InvalidateRegExpSpeciesProtector(native_context);
287289
} else if (isolate_->IsInAnyContext(
288-
holder_->map(isolate_).prototype(isolate_),
290+
receiver->map(isolate_).prototype(isolate_),
289291
Context::TYPED_ARRAY_PROTOTYPE_INDEX)) {
290292
if (!isolate_->IsTypedArraySpeciesLookupChainIntact()) return;
291293
isolate_->InvalidateTypedArraySpeciesProtector();
292294
}
293295
}
294296
} else if (*name_ == roots.next_string()) {
295-
if (isolate_->IsInAnyContext(
296-
*holder_, Context::INITIAL_ARRAY_ITERATOR_PROTOTYPE_INDEX)) {
297+
if (receiver->IsJSArrayIterator() ||
298+
isolate_->IsInAnyContext(
299+
*receiver, Context::INITIAL_ARRAY_ITERATOR_PROTOTYPE_INDEX)) {
297300
// Setting the next property of %ArrayIteratorPrototype% also needs to
298301
// invalidate the array iterator protector.
299302
if (!isolate_->IsArrayIteratorLookupChainIntact()) return;
300303
isolate_->InvalidateArrayIteratorProtector();
301-
} else if (isolate_->IsInAnyContext(
302-
*holder_, Context::INITIAL_MAP_ITERATOR_PROTOTYPE_INDEX)) {
304+
} else if (receiver->IsJSMapIterator() ||
305+
isolate_->IsInAnyContext(
306+
*receiver, Context::INITIAL_MAP_ITERATOR_PROTOTYPE_INDEX)) {
303307
if (!isolate_->IsMapIteratorLookupChainIntact()) return;
304308
isolate_->InvalidateMapIteratorProtector();
305-
} else if (isolate_->IsInAnyContext(
306-
*holder_, Context::INITIAL_SET_ITERATOR_PROTOTYPE_INDEX)) {
309+
} else if (receiver->IsJSSetIterator() ||
310+
isolate_->IsInAnyContext(
311+
*receiver, Context::INITIAL_SET_ITERATOR_PROTOTYPE_INDEX)) {
307312
if (!isolate_->IsSetIteratorLookupChainIntact()) return;
308313
isolate_->InvalidateSetIteratorProtector();
309-
} else if (isolate_->IsInAnyContext(
310-
*receiver_,
314+
} else if (receiver->IsJSStringIterator() ||
315+
isolate_->IsInAnyContext(
316+
*receiver,
311317
Context::INITIAL_STRING_ITERATOR_PROTOTYPE_INDEX)) {
312318
// Setting the next property of %StringIteratorPrototype% invalidates the
313319
// string iterator protector.
@@ -323,44 +329,54 @@ void LookupIterator::InternalUpdateProtector() {
323329
}
324330
// Setting the Symbol.species property of any Array, Promise or TypedArray
325331
// constructor invalidates the @@species protector
326-
if (isolate_->IsInAnyContext(*holder_, Context::ARRAY_FUNCTION_INDEX)) {
332+
if (isolate_->IsInAnyContext(*receiver, Context::ARRAY_FUNCTION_INDEX)) {
327333
if (!isolate_->IsArraySpeciesLookupChainIntact()) return;
328334
isolate_->CountUsage(
329335
v8::Isolate::UseCounterFeature::kArraySpeciesModified);
330336
isolate_->InvalidateArraySpeciesProtector();
331-
} else if (isolate_->IsInAnyContext(*holder_,
337+
} else if (isolate_->IsInAnyContext(*receiver,
332338
Context::PROMISE_FUNCTION_INDEX)) {
333339
if (!isolate_->IsPromiseSpeciesLookupChainIntact()) return;
334340
isolate_->InvalidatePromiseSpeciesProtector();
335-
} else if (isolate_->IsInAnyContext(*holder_,
341+
} else if (isolate_->IsInAnyContext(*receiver,
336342
Context::REGEXP_FUNCTION_INDEX)) {
337343
if (!isolate_->IsRegExpSpeciesLookupChainIntact(native_context)) return;
338344
isolate_->InvalidateRegExpSpeciesProtector(native_context);
339-
} else if (IsTypedArrayFunctionInAnyContext(isolate_, *holder_)) {
345+
} else if (IsTypedArrayFunctionInAnyContext(isolate_, *receiver)) {
340346
if (!isolate_->IsTypedArraySpeciesLookupChainIntact()) return;
341347
isolate_->InvalidateTypedArraySpeciesProtector();
342348
}
343349
} else if (*name_ == roots.is_concat_spreadable_symbol()) {
344350
if (!isolate_->IsIsConcatSpreadableLookupChainIntact()) return;
345351
isolate_->InvalidateIsConcatSpreadableProtector();
346352
} else if (*name_ == roots.iterator_symbol()) {
347-
if (holder_->IsJSArray(isolate_)) {
353+
if (receiver->IsJSArray(isolate_)) {
348354
if (!isolate_->IsArrayIteratorLookupChainIntact()) return;
349355
isolate_->InvalidateArrayIteratorProtector();
356+
} else if (receiver->IsJSSet(isolate_) || receiver->IsJSSetIterator() ||
357+
isolate_->IsInAnyContext(
358+
*receiver, Context::INITIAL_SET_ITERATOR_PROTOTYPE_INDEX) ||
359+
isolate_->IsInAnyContext(*receiver,
360+
Context::INITIAL_SET_PROTOTYPE_INDEX)) {
361+
if (isolate_->IsSetIteratorLookupChainIntact()) {
362+
isolate_->InvalidateSetIteratorProtector();
363+
}
364+
} else if (receiver->IsJSMapIterator() ||
365+
isolate_->IsInAnyContext(
366+
*receiver, Context::INITIAL_MAP_ITERATOR_PROTOTYPE_INDEX)) {
367+
if (isolate_->IsMapIteratorLookupChainIntact()) {
368+
isolate_->InvalidateMapIteratorProtector();
369+
}
350370
} else if (isolate_->IsInAnyContext(
351-
*holder_, Context::INITIAL_ITERATOR_PROTOTYPE_INDEX)) {
371+
*receiver, Context::INITIAL_ITERATOR_PROTOTYPE_INDEX)) {
352372
if (isolate_->IsMapIteratorLookupChainIntact()) {
353373
isolate_->InvalidateMapIteratorProtector();
354374
}
355375
if (isolate_->IsSetIteratorLookupChainIntact()) {
356376
isolate_->InvalidateSetIteratorProtector();
357377
}
358-
} else if (isolate_->IsInAnyContext(*holder_,
359-
Context::INITIAL_SET_PROTOTYPE_INDEX)) {
360-
if (!isolate_->IsSetIteratorLookupChainIntact()) return;
361-
isolate_->InvalidateSetIteratorProtector();
362378
} else if (isolate_->IsInAnyContext(
363-
*receiver_, Context::INITIAL_STRING_PROTOTYPE_INDEX)) {
379+
*receiver, Context::INITIAL_STRING_PROTOTYPE_INDEX)) {
364380
// Setting the Symbol.iterator property of String.prototype invalidates
365381
// the string iterator protector. Symbol.iterator can also be set on a
366382
// String wrapper, but not on a primitive string. We only support
@@ -372,7 +388,7 @@ void LookupIterator::InternalUpdateProtector() {
372388
if (!isolate_->IsPromiseResolveLookupChainIntact()) return;
373389
// Setting the "resolve" property on any %Promise% intrinsic object
374390
// invalidates the Promise.resolve protector.
375-
if (isolate_->IsInAnyContext(*holder_, Context::PROMISE_FUNCTION_INDEX)) {
391+
if (isolate_->IsInAnyContext(*receiver, Context::PROMISE_FUNCTION_INDEX)) {
376392
isolate_->InvalidatePromiseResolveProtector();
377393
}
378394
} else if (*name_ == roots.then_string()) {
@@ -384,10 +400,10 @@ void LookupIterator::InternalUpdateProtector() {
384400
// to guard the fast-path in AsyncGeneratorResolve, where we can skip
385401
// the ResolvePromise step and go directly to FulfillPromise if we
386402
// know that the Object.prototype doesn't contain a "then" method.
387-
if (holder_->IsJSPromise(isolate_) ||
388-
isolate_->IsInAnyContext(*holder_,
403+
if (receiver->IsJSPromise(isolate_) ||
404+
isolate_->IsInAnyContext(*receiver,
389405
Context::INITIAL_OBJECT_PROTOTYPE_INDEX) ||
390-
isolate_->IsInAnyContext(*holder_, Context::PROMISE_PROTOTYPE_INDEX)) {
406+
isolate_->IsInAnyContext(*receiver, Context::PROMISE_PROTOTYPE_INDEX)) {
391407
isolate_->InvalidatePromiseThenProtector();
392408
}
393409
}

test/mjsunit/es6/map-iterator-8.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ assertEquals([], [...map.keys()]);
2525
assertEquals([], [...map.values()]);
2626
assertEquals([], [...iterator]);
2727

28-
assertFalse(%SetIteratorProtector());
28+
assertTrue(%SetIteratorProtector());
2929
assertEquals([1,2,3], [...set]);
3030
assertEquals([[1,1],[2,2],[3,3]], [...set.entries()]);
3131
assertEquals([1,2,3], [...set.keys()]);

test/mjsunit/es6/map-iterator-9.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ assertEquals([1,2,3], [...map.keys()]);
2323
assertEquals([2,3,4], [...map.values()]);
2424
assertEquals([], [...iterator]);
2525

26-
assertFalse(%SetIteratorProtector());
26+
assertTrue(%SetIteratorProtector());
2727
assertEquals([1,2,3], [...set]);
2828
assertEquals([[1,1],[2,2],[3,3]], [...set.entries()]);
2929
assertEquals([1,2,3], [...set.keys()]);

test/mjsunit/es6/set-iterator-8.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ assertTrue(%SetIteratorProtector());
1818
var iterator = set.keys();
1919
iterator.__proto__[Symbol.iterator] = () => ({next: () => ({done: true})});
2020

21-
assertFalse(%MapIteratorProtector());
21+
assertTrue(%MapIteratorProtector());
2222
assertEquals([[1,2], [2,3], [3,4]], [...map]);
2323
assertEquals([[1,2], [2,3], [3,4]], [...map.entries()]);
2424
assertEquals([1,2,3], [...map.keys()]);

test/mjsunit/es6/set-iterator-9.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ assertTrue(%SetIteratorProtector());
1717
var iterator = set.keys();
1818
iterator[Symbol.iterator] = () => ({next: () => ({done: true})});
1919

20-
assertFalse(%MapIteratorProtector());
20+
assertTrue(%MapIteratorProtector());
2121
assertEquals([[1,2], [2,3], [3,4]], [...map]);
2222
assertEquals([[1,2], [2,3], [3,4]], [...map.entries()]);
2323
assertEquals([1,2,3], [...map.keys()]);

test/mjsunit/regress/regress-9466.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright 2019 the V8 project authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
const o = [];
6+
o.__proto__ = {};
7+
o.constructor = function() {};
8+
o.constructor[Symbol.species] = function f() {};
9+
o.__proto__ = Array.prototype;
10+
assertEquals(o.constructor[Symbol.species], o.concat([1,2,3]).constructor);

0 commit comments

Comments
 (0)