Bug 754311 - Null out the private of soon-to-be-transplanted reflectors _after_ copying their properties onto the holder. r=mrbkap

This commit is contained in:
Bobby Holley 2012-05-14 23:30:07 +02:00
parent 3165006395
commit 4c3278d85a
4 changed files with 49 additions and 2 deletions

View File

@ -0,0 +1,21 @@
<html>
<head>
<script type="application/javascript">
function boom() {
// Don't crash when transplanting wrappers with cyclic references.
document.documentElement.dataset.xml = document.documentElement.dataset;
document.open();
// Tell the parent window that we're done.
window.parent.allDone();
}
// This needs to do a round-trip through the event loop to work right.
window.onload = function() { setTimeout(boom, 0); };
</script>
</head>
<body>
</body>
</html>

View File

@ -0,0 +1,16 @@
<html class="reftest-wait">
<head>
<script type="application/javascript">
// The actual crashing code does document.write, which doesn't play
// well with |reftest-wait|. So we load it in an iframe.
function allDone() {
window.document.documentElement.removeAttribute("class");
}
</script>
</head>
<body>
<iframe src="754311-iframe.html"></iframe>
</body>
</html>

View File

@ -36,3 +36,4 @@ load 639737-1.html
load 648206-1.html
load 705875.html
load 723465.html
load 754311.html

View File

@ -1642,8 +1642,6 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCCallContext& ccx,
if (!newobj)
return NS_ERROR_FAILURE;
JS_SetPrivate(flat, nsnull);
JSObject *propertyHolder =
JS_NewObjectWithGivenProto(ccx, NULL, NULL, aNewParent);
if (!propertyHolder || !JS_CopyPropertiesFrom(ccx, propertyHolder, flat))
@ -1659,6 +1657,17 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCCallContext& ccx,
return NS_ERROR_FAILURE;
}
// Null out the private of the JS reflector. If we don't, we'll end up
// with two JS objects with the same WN in their private slot, and both
// will try to delete it during finalization. The one in this
// compartment will actually go away quite soon, because we swap() it
// with another object during the transplant and let that object die.
//
// NB: It's important to do this _after_ copying the properties to
// propertyHolder. Otherwise, an object with |foo.x === foo| will
// crash when JS_CopyPropertiesFrom tries to call wrap() on foo.x.
JS_SetPrivate(flat, nsnull);
JSObject *ww = wrapper->GetWrapper();
if (ww) {
JSObject *newwrapper;