Bug 1591342: When setting breakpoints, require usable cross-compartment wrappers. r=jonco

When the `Debugger` API sets a breakpoint in a JSScript or wasm::Instance, the
BreakpointSite and Breakpoint objects belong to the code's compartment
(logically, at least - they're C++ objects and don't actually have any
compartment). Since a `Debugger` and its debuggees must be in separate
compartments, the Breakpoint's references to its owning `Debugger` and its
handler object must go through cross-compartment wrappers.

If we have nuked the `Debugger`'s compartment, it's not clear how we're still
trying to set breakpoints in its debuggees, but we should at least throw an
error, to capture a JavaScript stack when it occurs.

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Jim Blandy 2019-11-02 02:05:01 +00:00
parent de66507e5e
commit 4635915c52
2 changed files with 31 additions and 4 deletions

View File

@ -2043,6 +2043,22 @@ struct DebuggerScript::SetBreakpointMatcher {
RootedObject handler_;
RootedObject debuggerObject_;
bool wrapCrossCompartmentEdges() {
if (!cx_->compartment()->wrap(cx_, &handler_) ||
!cx_->compartment()->wrap(cx_, &debuggerObject_)) {
return false;
}
// If the Debugger's compartment has killed incoming wrappers, we may not
// have gotten usable results from the 'wrap' calls. Treat it as a failure.
if (IsDeadProxyObject(handler_) || IsDeadProxyObject(debuggerObject_)) {
ReportAccessDenied(cx_);
return false;
}
return true;
}
public:
explicit SetBreakpointMatcher(JSContext* cx, Debugger* dbg, size_t offset,
HandleObject handler)
@ -2076,8 +2092,7 @@ struct DebuggerScript::SetBreakpointMatcher {
// A Breakpoint belongs logically to its script's compartment, so its
// references to its Debugger and handler must be properly wrapped.
AutoRealm ar(cx_, script);
if (!cx_->compartment()->wrap(cx_, &handler_) ||
!cx_->compartment()->wrap(cx_, &debuggerObject_)) {
if (!wrapCrossCompartmentEdges()) {
return false;
}
@ -2115,8 +2130,7 @@ struct DebuggerScript::SetBreakpointMatcher {
// A Breakpoint belongs logically to its Instance's compartment, so its
// references to its Debugger and handler must be properly wrapped.
AutoRealm ar(cx_, wasmInstance);
if (!cx_->compartment()->wrap(cx_, &handler_) ||
!cx_->compartment()->wrap(cx_, &debuggerObject_)) {
if (!wrapCrossCompartmentEdges()) {
return false;
}

View File

@ -0,0 +1,13 @@
// |jit-test| error: Permission denied to access object
// jsfunfuzz-generated
newGlobal({ sameCompartmentAs: this });
nukeAllCCWs();
// Adapted from randomly chosen testcase: js/src/jit-test/tests/debug/clear-old-analyses-02.js
var g = newGlobal({
newCompartment: true
});
var dbg = Debugger();
gw = dbg.addDebuggee(g);
g.eval("" + function fib() {});
gw.makeDebuggeeValue(g.fib).script.setBreakpoint(0, {});