зеркало из https://github.com/mozilla/gecko-dev.git
Bug 922009 - MOZ_CRASH when trying to transplant objects with SCSWs. r=mrbkap
This commit is contained in:
Родитель
9cb1da54a5
Коммит
2dcd8b769e
|
@ -1756,20 +1756,9 @@ ReparentWrapper(JSContext* aCx, JS::HandleObject aObjArg)
|
|||
if (ww != aObj) {
|
||||
MOZ_ASSERT(cache->HasSystemOnlyWrapper());
|
||||
|
||||
JS::RootedObject newwrapper(aCx,
|
||||
xpc::WrapperFactory::WrapSOWObject(aCx, newobj));
|
||||
if (!newwrapper) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
// Oops. We don't support transplanting objects with SOWs anymore.
|
||||
MOZ_CRASH();
|
||||
|
||||
// Ok, now we do the special object-plus-wrapper transplant.
|
||||
ww = xpc::TransplantObjectWithWrapper(aCx, aObj, ww, newobj, newwrapper);
|
||||
if (!ww) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
aObj = newobj;
|
||||
SetSystemOnlyWrapperSlot(aObj, JS::ObjectValue(*ww));
|
||||
} else {
|
||||
aObj = xpc::TransplantObject(aCx, aObj, newobj);
|
||||
if (!aObj) {
|
||||
|
|
|
@ -1267,96 +1267,6 @@ JS_TransplantObject(JSContext *cx, HandleObject origobj, HandleObject target)
|
|||
return newIdentity;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some C++ objects (such as the location object and XBL) require both an XPConnect
|
||||
* reflector and a security wrapper for that reflector. We expect that there are
|
||||
* no live references to the reflector, so when we perform the transplant we turn
|
||||
* the security wrapper into a cross-compartment wrapper. Just in case there
|
||||
* happen to be live references to the reflector, we swap it out to limit the harm.
|
||||
*/
|
||||
JS_FRIEND_API(JSObject *)
|
||||
js_TransplantObjectWithWrapper(JSContext *cx,
|
||||
HandleObject origobj,
|
||||
HandleObject origwrapper,
|
||||
HandleObject targetobj,
|
||||
HandleObject targetwrapper)
|
||||
{
|
||||
AutoMaybeTouchDeadZones agc(cx);
|
||||
AutoDisableProxyCheck adpc(cx->runtime());
|
||||
|
||||
AssertHeapIsIdle(cx);
|
||||
JS_ASSERT(!origobj->is<CrossCompartmentWrapperObject>());
|
||||
JS_ASSERT(!origwrapper->is<CrossCompartmentWrapperObject>());
|
||||
JS_ASSERT(!targetobj->is<CrossCompartmentWrapperObject>());
|
||||
JS_ASSERT(!targetwrapper->is<CrossCompartmentWrapperObject>());
|
||||
|
||||
RootedObject newWrapper(cx);
|
||||
JSCompartment *destination = targetobj->compartment();
|
||||
|
||||
// |origv| is the map entry we're looking up. The map entries are going to
|
||||
// be for |origobj|, not |origwrapper|.
|
||||
Value origv = ObjectValue(*origobj);
|
||||
|
||||
// There might already be a wrapper for the original object in the new
|
||||
// compartment.
|
||||
if (WrapperMap::Ptr p = destination->lookupWrapper(origv)) {
|
||||
// There is. Make the existing cross-compartment wrapper a same-
|
||||
// compartment wrapper.
|
||||
newWrapper = &p->value.toObject();
|
||||
|
||||
// When we remove origv from the wrapper map, its wrapper, newWrapper,
|
||||
// must immediately cease to be a cross-compartment wrapper. Neuter it.
|
||||
destination->removeWrapper(p);
|
||||
NukeCrossCompartmentWrapper(cx, newWrapper);
|
||||
|
||||
if (!JSObject::swap(cx, newWrapper, targetwrapper))
|
||||
MOZ_CRASH();
|
||||
} else {
|
||||
// Otherwise, use the passed-in wrapper as the same-compartment wrapper.
|
||||
newWrapper = targetwrapper;
|
||||
}
|
||||
|
||||
// Now, iterate through other scopes looking for references to the old
|
||||
// object. Note that the entries in the maps are for |origobj| and not
|
||||
// |origwrapper|. They need to be updated to point at the new object.
|
||||
if (!RemapAllWrappersForObject(cx, origobj, targetobj))
|
||||
MOZ_CRASH();
|
||||
|
||||
// Lastly, update things in the original compartment. Our invariants dictate
|
||||
// that the original compartment can only have one cross-compartment wrapper
|
||||
// to the new object. So we choose to update |origwrapper|, not |origobj|,
|
||||
// since there are probably no live direct intra-compartment references to
|
||||
// |origobj|.
|
||||
{
|
||||
AutoCompartment ac(cx, origobj);
|
||||
|
||||
// We can't be sure that the reflector is completely dead. This is bad,
|
||||
// because it is in a weird state. To minimize potential harm we create
|
||||
// a new unreachable dummy object and swap it with the reflector.
|
||||
// After the swap we have a possibly-live object that isn't dangerous,
|
||||
// and a possibly-dangerous object that isn't live.
|
||||
ProxyOptions options;
|
||||
if (!IsBackgroundFinalized(origobj->tenuredGetAllocKind()))
|
||||
options.setForceForegroundFinalization(true);
|
||||
RootedObject reflectorGuts(cx, NewDeadProxyObject(cx, JS_GetGlobalForObject(cx, origobj),
|
||||
options));
|
||||
if (!reflectorGuts || !JSObject::swap(cx, origobj, reflectorGuts))
|
||||
MOZ_CRASH();
|
||||
|
||||
// Turn origwrapper into a CCW to the new object.
|
||||
RootedObject wrapperGuts(cx, targetobj);
|
||||
if (!JS_WrapObject(cx, &wrapperGuts))
|
||||
MOZ_CRASH();
|
||||
JS_ASSERT(Wrapper::wrappedObject(wrapperGuts) == targetobj);
|
||||
if (!JSObject::swap(cx, origwrapper, wrapperGuts))
|
||||
MOZ_CRASH();
|
||||
origwrapper->compartment()->putWrapper(ObjectValue(*targetobj),
|
||||
ObjectValue(*origwrapper));
|
||||
}
|
||||
|
||||
return newWrapper;
|
||||
}
|
||||
|
||||
/*
|
||||
* Recompute all cross-compartment wrappers for an object, resetting state.
|
||||
* Gecko uses this to clear Xray wrappers when doing a navigation that reuses
|
||||
|
|
|
@ -1768,13 +1768,6 @@ JS_WrapId(JSContext *cx, jsid *idp);
|
|||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_TransplantObject(JSContext *cx, JS::Handle<JSObject*> origobj, JS::Handle<JSObject*> target);
|
||||
|
||||
extern JS_FRIEND_API(JSObject *)
|
||||
js_TransplantObjectWithWrapper(JSContext *cx,
|
||||
JS::Handle<JSObject*> origobj,
|
||||
JS::Handle<JSObject*> origwrapper,
|
||||
JS::Handle<JSObject*> targetobj,
|
||||
JS::Handle<JSObject*> targetwrapper);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_RefreshCrossCompartmentWrappers(JSContext *cx, JSObject *ob);
|
||||
|
||||
|
|
|
@ -1463,18 +1463,10 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCWrappedNativeScope* aOldScope,
|
|||
if (ww) {
|
||||
RootedObject newwrapper(cx);
|
||||
MOZ_ASSERT(wrapper->NeedsSOW(), "weird wrapper wrapper");
|
||||
newwrapper = xpc::WrapperFactory::WrapSOWObject(cx, newobj);
|
||||
if (!newwrapper)
|
||||
MOZ_CRASH();
|
||||
|
||||
// Ok, now we do the special object-plus-wrapper transplant.
|
||||
ww = xpc::TransplantObjectWithWrapper(cx, flat, ww, newobj,
|
||||
newwrapper);
|
||||
if (!ww)
|
||||
MOZ_CRASH();
|
||||
// Oops. We don't support transplanting objects with SOWs anymore.
|
||||
MOZ_CRASH();
|
||||
|
||||
flat = newobj;
|
||||
wrapper->SetWrapper(ww);
|
||||
} else {
|
||||
flat = xpc::TransplantObject(cx, flat, newobj);
|
||||
if (!flat)
|
||||
|
|
|
@ -38,11 +38,6 @@ namespace xpc {
|
|||
JSObject *
|
||||
TransplantObject(JSContext *cx, JS::HandleObject origobj, JS::HandleObject target);
|
||||
|
||||
JSObject *
|
||||
TransplantObjectWithWrapper(JSContext *cx,
|
||||
JS::HandleObject origobj, JS::HandleObject origwrapper,
|
||||
JS::HandleObject targetobj, JS::HandleObject targetwrapper);
|
||||
|
||||
// Return a raw XBL scope object corresponding to contentScope, which must
|
||||
// be an object whose global is a DOM window.
|
||||
//
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<bindings xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml">
|
||||
<binding id="testBinding2">
|
||||
<implementation>
|
||||
<constructor>
|
||||
document.body.appendChild(parent.wrappedJSObject.nac);
|
||||
parent.wrappedJSObject.ok(true, "Didn't crash");
|
||||
parent.wrappedJSObject.SimpleTest.finish();
|
||||
</constructor>
|
||||
</implementation>
|
||||
</binding>
|
||||
</bindings>
|
||||
<script type="application/javascript">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="bindingSink" style="-moz-binding: url(#testBinding2);"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -30,7 +30,6 @@ support-files =
|
|||
file_exnstack.html
|
||||
file_expandosharing.html
|
||||
file_mozMatchesSelector.html
|
||||
file_nac.xhtml
|
||||
file_nodelists.html
|
||||
file_wrappers-2.html
|
||||
inner.html
|
||||
|
|
|
@ -45,11 +45,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=914618
|
|||
checkThrows(new iwin.Function('nac.toString();'));
|
||||
checkThrows(new iwin.Function('nac.textContent;'));
|
||||
|
||||
// Try adopting the NAC into another scope using a different XBL binding.
|
||||
// The <constructor> in file_nac.xhtml will call SimpleTest.finish().
|
||||
var ifr2 = document.createElement('iframe');
|
||||
document.body.appendChild(ifr2);
|
||||
ifr2.contentWindow.location = 'file_nac.xhtml';
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
]]>
|
||||
|
|
|
@ -667,25 +667,6 @@ TransplantObject(JSContext *cx, JS::HandleObject origobj, JS::HandleObject targe
|
|||
return newIdentity;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
TransplantObjectWithWrapper(JSContext *cx,
|
||||
HandleObject origobj, HandleObject origwrapper,
|
||||
HandleObject targetobj, HandleObject targetwrapper)
|
||||
{
|
||||
RootedObject oldWaiver(cx, WrapperFactory::GetXrayWaiver(origobj));
|
||||
RootedObject newSameCompartmentWrapper(cx,
|
||||
js_TransplantObjectWithWrapper(cx, origobj, origwrapper, targetobj,
|
||||
targetwrapper));
|
||||
if (!newSameCompartmentWrapper || !oldWaiver)
|
||||
return newSameCompartmentWrapper;
|
||||
|
||||
RootedObject newIdentity(cx, Wrapper::wrappedObject(newSameCompartmentWrapper));
|
||||
MOZ_ASSERT(!js::IsWrapper(newIdentity));
|
||||
if (!FixWaiverAfterTransplant(cx, oldWaiver, newIdentity))
|
||||
return nullptr;
|
||||
return newSameCompartmentWrapper;
|
||||
}
|
||||
|
||||
nsIGlobalObject *
|
||||
GetNativeForGlobal(JSObject *obj)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче