Bug 1525346. Fix the cross-compartment bug in MaybeCrossOriginObject::enumerate. r=jandem

Differential Revision: https://phabricator.services.mozilla.com/D18714

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Boris Zbarsky 2019-02-05 18:45:27 +00:00
Родитель a35b931962
Коммит c48f274465
4 изменённых файлов: 42 добавлений и 10 удалений

Просмотреть файл

@ -423,11 +423,37 @@ template <typename Base>
JSObject* MaybeCrossOriginObject<Base>::enumerate(
JSContext* cx, JS::Handle<JSObject*> proxy) const {
// We want to avoid any possible magic here and just do the BaseProxyHandler
// thing of using our property keys to enumerate.
//
// Note that we do not need to enter the Realm of "proxy" here, nor do we want
// to: if this is a cross-origin access we want to handle it appropriately.
return js::BaseProxyHandler::enumerate(cx, proxy);
// thing of using our property keys to enumerate. But we can't actually call
// BaseProxyHandler::enumerate, because that does two things: (1) Get the keys
// and (2) create the iterator object. We want to do (1) in our current
// Realm, because if this is a cross-origin access we want to handle it
// appropriately. But the iterator object needs to be created in the Realm of
// "proxy", because it might involve changing "proxy"'s shape, and that needs
// to happen in at least the same zone as "proxy".
JS::AutoIdVector props(cx);
if (!GetPropertyKeys(cx, proxy, 0, &props)) {
return nullptr;
}
// Create the iterator object in the Realm of "proxy".
JS::Rooted<JSObject*> iterator(cx);
{ // Scope for JSAutoRealm
JSAutoRealm ar(cx, proxy);
for (auto& id : props) {
JS_MarkCrossZoneId(cx, id);
}
iterator = EnumeratedIdVectorToIterator(cx, proxy, props);
if (!iterator) {
return nullptr;
}
}
// And now put things back in the Realm we started with.
if (!MaybeWrapObject(cx, &iterator)) {
return nullptr;
}
return iterator;
}
// Force instantiations of the out-of-line template methods we need.

Просмотреть файл

@ -2798,6 +2798,12 @@ extern JS_FRIEND_API void LogDtor(void* self, const char* type, uint32_t sz);
*/
extern JS_FRIEND_API uint64_t GetGCHeapUsageForObjectZone(JSObject* obj);
/**
* Create an iterator for the given list of props and the given object
* being iterated.
*/
extern JS_FRIEND_API JSObject* EnumeratedIdVectorToIterator(
JSContext* cx, JS::HandleObject obj, JS::AutoIdVector& props);
} /* namespace js */
#endif /* jsfriendapi_h */

Просмотреть файл

@ -798,6 +798,8 @@ static inline PropertyIteratorObject* VectorToKeyIterator(JSContext* cx,
HandleObject obj,
AutoIdVector& props,
uint32_t numGuards) {
MOZ_ASSERT(cx->compartment() == obj->compartment(),
"We may end up allocating shapes in the wrong zone!");
if (obj->isSingleton() && !JSObject::setIteratedSingleton(cx, obj)) {
return nullptr;
}
@ -806,8 +808,9 @@ static inline PropertyIteratorObject* VectorToKeyIterator(JSContext* cx,
return CreatePropertyIterator(cx, obj, props, numGuards, 0);
}
JSObject* js::EnumeratedIdVectorToIterator(JSContext* cx, HandleObject obj,
AutoIdVector& props) {
JS_FRIEND_API JSObject* js::EnumeratedIdVectorToIterator(JSContext* cx,
HandleObject obj,
AutoIdVector& props) {
return VectorToKeyIterator(cx, obj, props, 0);
}

Просмотреть файл

@ -369,9 +369,6 @@ JSObject* GetIterator(JSContext* cx, HandleObject obj);
PropertyIteratorObject* LookupInIteratorCache(JSContext* cx, HandleObject obj);
JSObject* EnumeratedIdVectorToIterator(JSContext* cx, HandleObject obj,
AutoIdVector& props);
JSObject* NewEmptyPropertyIterator(JSContext* cx);
JSObject* ValueToIterator(JSContext* cx, HandleValue vp);