зеркало из https://github.com/mozilla/gecko-dev.git
Bug 866823 - Handle standard prototype remapping in PrepareForWrapping. r=gabor,mrbkap
This commit is contained in:
Родитель
a7596f01a7
Коммит
7c5384c4e9
|
@ -156,6 +156,41 @@ WrapperFactory::PrepareForWrapping(JSContext *cx, HandleObject scope,
|
|||
if (IS_SLIM_WRAPPER(obj) && !MorphSlimWrapper(cx, obj))
|
||||
return nullptr;
|
||||
|
||||
// If the object being wrapped is a prototype for a standard class and the
|
||||
// wrapper does not subsumes the wrappee, use the one from the content
|
||||
// compartment. This is generally safer all-around, and in the COW case this
|
||||
// lets us safely take advantage of things like .forEach() via the
|
||||
// ChromeObjectWrapper machinery.
|
||||
//
|
||||
// If the prototype chain of chrome object |obj| looks like this:
|
||||
//
|
||||
// obj => foo => bar => chromeWin.StandardClass.prototype
|
||||
//
|
||||
// The prototype chain of COW(obj) looks lke this:
|
||||
//
|
||||
// COW(obj) => COW(foo) => COW(bar) => contentWin.StandardClass.prototype
|
||||
//
|
||||
// NB: We now remap all non-subsuming access of standard prototypes.
|
||||
bool subsumes = AccessCheck::subsumes(js::GetContextCompartment(cx),
|
||||
js::GetObjectCompartment(obj));
|
||||
XrayType xrayType = GetXrayType(obj);
|
||||
if (!subsumes && xrayType == NotXray) {
|
||||
JSProtoKey key = JSProto_Null;
|
||||
{
|
||||
JSAutoCompartment ac(cx, obj);
|
||||
key = JS_IdentifyClassPrototype(cx, obj);
|
||||
}
|
||||
if (key != JSProto_Null) {
|
||||
RootedObject homeProto(cx);
|
||||
if (!JS_GetClassPrototype(cx, key, homeProto.address()))
|
||||
return nullptr;
|
||||
MOZ_ASSERT(homeProto);
|
||||
// No need to double-wrap here. We should never have waivers to
|
||||
// COWs.
|
||||
return homeProto;
|
||||
}
|
||||
}
|
||||
|
||||
// Now, our object is ready to be wrapped, but several objects (notably
|
||||
// nsJSIIDs) have a wrapper per scope. If we are about to wrap one of
|
||||
// those objects in a security wrapper, then we need to hand back the
|
||||
|
@ -441,41 +476,7 @@ WrapperFactory::Rewrap(JSContext *cx, HandleObject existing, HandleObject obj,
|
|||
wrapper = SelectWrapper(securityWrapper, wantXrays, xrayType, waiveXrays);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// If the prototype of a chrome object being wrapped in content is a prototype
|
||||
// for a standard class, use the one from the content compartment so
|
||||
// that we can safely take advantage of things like .forEach().
|
||||
//
|
||||
// If the prototype chain of chrome object |obj| looks like this:
|
||||
//
|
||||
// obj => foo => bar => chromeWin.StandardClass.prototype
|
||||
//
|
||||
// The prototype chain of COW(obj) looks lke this:
|
||||
//
|
||||
// COW(obj) => COW(foo) => COW(bar) => contentWin.StandardClass.prototype
|
||||
if (wrapper == &ChromeObjectWrapper::singleton) {
|
||||
JSProtoKey key = JSProto_Null;
|
||||
{
|
||||
JSAutoCompartment ac(cx, obj);
|
||||
RootedObject unwrappedProto(cx);
|
||||
if (!js::GetObjectProto(cx, obj, &unwrappedProto))
|
||||
return NULL;
|
||||
if (unwrappedProto && IsCrossCompartmentWrapper(unwrappedProto))
|
||||
unwrappedProto = Wrapper::wrappedObject(unwrappedProto);
|
||||
if (unwrappedProto) {
|
||||
JSAutoCompartment ac2(cx, unwrappedProto);
|
||||
key = JS_IdentifyClassPrototype(cx, unwrappedProto);
|
||||
}
|
||||
}
|
||||
if (key != JSProto_Null) {
|
||||
RootedObject homeProto(cx);
|
||||
if (!JS_GetClassPrototype(cx, key, homeProto.address()))
|
||||
return NULL;
|
||||
MOZ_ASSERT(homeProto);
|
||||
proxyProto = homeProto;
|
||||
}
|
||||
|
||||
// This shouldn't happen, but do a quick check to make some dumb addon
|
||||
// doesn't expose chrome eval or Function().
|
||||
JSFunction *fun = JS_GetObjectFunction(obj);
|
||||
|
|
Загрузка…
Ссылка в новой задаче