From 20cf72c49d22282afe0ac5394c05f51db884b813 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bargull?= Date: Thu, 28 Mar 2019 17:27:49 +0000 Subject: [PATCH] Bug 1538542: Report an error in the transplant testing function when new wrappers can't be created. r=jandem And also assert this case can't happen in the browser case. Differential Revision: https://phabricator.services.mozilla.com/D24883 --HG-- extra : moz-landing-system : lando --- dom/bindings/BindingUtils.cpp | 6 ++++++ js/src/jit-test/tests/auto-regress/bug1538542-1.js | 13 +++++++++++++ js/src/jit-test/tests/auto-regress/bug1538542-2.js | 13 +++++++++++++ js/src/shell/js.cpp | 14 +++++++++++--- 4 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 js/src/jit-test/tests/auto-regress/bug1538542-1.js create mode 100644 js/src/jit-test/tests/auto-regress/bug1538542-2.js diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp index adb966eff91b..d9d939dcd87b 100644 --- a/dom/bindings/BindingUtils.cpp +++ b/dom/bindings/BindingUtils.cpp @@ -2196,6 +2196,12 @@ void UpdateReflectorGlobal(JSContext* aCx, JS::Handle aObjArg, return; } + // Assert it's possible to create wrappers when |aObj| and |newobj| are in + // different compartments. + MOZ_ASSERT_IF( + js::GetObjectCompartment(aObj) != js::GetObjectCompartment(newobj), + js::AllowNewWrapper(js::GetObjectCompartment(aObj), newobj)); + JS::Rooted propertyHolder(aCx); JS::Rooted copyFrom(aCx, isProxy ? expandoObject : aObj); if (copyFrom) { diff --git a/js/src/jit-test/tests/auto-regress/bug1538542-1.js b/js/src/jit-test/tests/auto-regress/bug1538542-1.js new file mode 100644 index 000000000000..5057de6f9450 --- /dev/null +++ b/js/src/jit-test/tests/auto-regress/bug1538542-1.js @@ -0,0 +1,13 @@ +var lfOffThreadGlobal = newGlobal(); +nukeAllCCWs(); +const thisGlobal = this; +const otherGlobalNewCompartment = newGlobal({ + newCompartment: true +}); +let { transplant } = transplantableObject(); + +// Just don't crash. +try { + transplant(otherGlobalNewCompartment); + transplant(thisGlobal); +} catch {} diff --git a/js/src/jit-test/tests/auto-regress/bug1538542-2.js b/js/src/jit-test/tests/auto-regress/bug1538542-2.js new file mode 100644 index 000000000000..3efc05ceb683 --- /dev/null +++ b/js/src/jit-test/tests/auto-regress/bug1538542-2.js @@ -0,0 +1,13 @@ +var lfOffThreadGlobal = newGlobal(); +nukeAllCCWs(); +const thisGlobal = this; +const otherGlobalNewCompartment = newGlobal({ + newCompartment: false +}); +let { transplant } = transplantableObject(); + +// Just don't crash. +try { + transplant(otherGlobalNewCompartment); + transplant(thisGlobal); +} catch {} diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index e2bd9cfb60fc..efa425daae97 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -8142,9 +8142,11 @@ static bool TransplantObject(JSContext* cx, unsigned argc, Value* vp) { // 1. Check the recursion depth using CheckRecursionLimitConservative. // 2. Enter the target compartment. // 3. Clone the source object using JS_CloneObject. - // 4. Copy all properties from source to a temporary holder object. - // 5. Actually transplant the object. - // 6. And finally copy the properties back to the source object. + // 4. Check if new wrappers can be created if source and target are in + // different compartments. + // 5. Copy all properties from source to a temporary holder object. + // 6. Actually transplant the object. + // 7. And finally copy the properties back to the source object. // // As an extension to the algorithm in UpdateReflectorGlobal, we also allow // to transplant an object into the same compartment as the source object to @@ -8178,6 +8180,12 @@ static bool TransplantObject(JSContext* cx, unsigned argc, Value* vp) { return false; } + if (GetObjectCompartment(source) != GetObjectCompartment(target) && + !AllowNewWrapper(GetObjectCompartment(source), target)) { + JS_ReportErrorASCII(cx, "Cannot transplant into nuked compartment"); + return false; + } + RootedObject copyFrom(cx, isProxy ? expandoObject : source); RootedObject propertyHolder(cx, JS_NewObjectWithGivenProto(cx, nullptr, nullptr));