tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit a8dfb8b4c814b294b02f737575a15810107c60c9
parent 52fdd186700f329256cc2fd782ad6a48d0549fdb
Author: Jon Coppeard <jcoppeard@mozilla.com>
Date:   Tue,  2 Dec 2025 08:26:44 +0000

Bug 2003100 - Suppress GC during wrapper remapping r=sfink

We rely on tracing a CCW to the debugger from a script with a breakpoint that's
in another compartment.  The problem here is that wrapper remapping can trigger
a GC after nuking the original CCW but before remapping is complete, meaning
that we wouldn't trace the debugger target in this case.

The patch suppresses GC during remapping.

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

Diffstat:
Ajs/src/jit-test/tests/gc/bug-2003100.js | 9+++++++++
Mjs/src/proxy/CrossCompartmentWrapper.cpp | 7+++++++
2 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/js/src/jit-test/tests/gc/bug-2003100.js b/js/src/jit-test/tests/gc/bug-2003100.js @@ -0,0 +1,9 @@ +var dbgA = new Debugger; +var g1 = newGlobal({newCompartment: true}); +g1.eval('function g1f() { print("Weltuntergang"); }'); +var DOAg1 = dbgA.addDebuggee(g1); +var DOAg1f = DOAg1.getOwnPropertyDescriptor('g1f').value; +DOAg1f.script.setBreakpoint(0, { hit: () => { logA += '1'; } }); +gczeal(2,1) +class Base { } +recomputeWrappers(); diff --git a/js/src/proxy/CrossCompartmentWrapper.cpp b/js/src/proxy/CrossCompartmentWrapper.cpp @@ -508,6 +508,9 @@ void js::RemapWrapper(JSContext* cx, JSObject* wobjArg, AutoDisableProxyCheck adpc; + // This can't GC (and RemapDeadWrapper suppresses it). + JS::AutoAssertNoGC nogc(cx); + // If we're mapping to a different target (as opposed to just recomputing // for the same target), we must not have an existing wrapper for the new // target, otherwise this will break. @@ -549,6 +552,10 @@ void js::RemapDeadWrapper(JSContext* cx, HandleObject wobj, AutoDisableProxyCheck adpc; + // Suppress GC while we manipulate the wrapper map so that it can't observe + // intervening state. + gc::AutoSuppressGC nogc(cx); + // wobj is not a cross-compartment wrapper, so we can use nonCCWRealm. Realm* wrealm = wobj->nonCCWRealm();