1 // Bug 1117242: Test calling SavedFrame getters from globals that don't subsume
2 // that frame's principals.
4 const {addDebuggerToGlobal} = ChromeUtils.importESModule("resource://gre/modules/jsdebugger.sys.mjs");
5 addDebuggerToGlobal(globalThis);
7 const lowP = Services.scriptSecurityManager.createNullPrincipal({});
8 const midP = [lowP, "http://other.com"];
9 const highP = Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal);
11 const low = new Cu.Sandbox(lowP);
12 const mid = new Cu.Sandbox(midP);
13 const high = new Cu.Sandbox(highP);
16 // Test that the priveleged view of a SavedFrame from a subsumed compartment
17 // is the same view that the subsumed compartment gets. Create the following
18 // chain of function calls (with some intermediate system-principaled frames
19 // due to implementation):
21 // low.lowF -> mid.midF -> high.highF -> high.saveStack
23 // Where high.saveStack gets monkey patched to create stacks in each of our
26 Cu.evalInSandbox("function highF() { return saveStack(); }", high);
28 mid.highF = () => high.highF();
29 Cu.evalInSandbox("function midF() { return highF(); }", mid);
31 low.midF = () => mid.midF();
32 Cu.evalInSandbox("function lowF() { return midF(); }", low);
41 frames: ["midF", "lowF"],
45 frames: ["getSavedFrameInstanceFromSandbox",
58 for (let { sandbox, frames } of expected) {
59 high.saveStack = function saveStack() {
60 return getSavedFrameInstanceFromSandbox(sandbox);
63 const xrayStack = low.lowF();
64 equal(xrayStack.functionDisplayName, "getSavedFrameInstanceFromSandbox",
65 "Xrays should always be able to see everything.");
67 let waived = Cu.waiveXrays(xrayStack);
70 "There should still be more expected frames while we have actual frames.");
71 equal(waived.functionDisplayName, frames.shift(),
72 "The waived wrapper should give us the stack's compartment's view.");
73 waived = waived.parent;
78 // Get a SavedFrame instance from inside the given sandbox.
80 // We can't use Cu.getJSTestingFunctions().saveStack() because Cu isn't
81 // available to sandboxes that don't have the system principal. The easiest way
82 // to get the SavedFrame is to use the Debugger API to track allocation sites
83 // and then do an allocation.
84 function getSavedFrameInstanceFromSandbox(sandbox) {
85 const dbg = new Debugger(sandbox);
87 dbg.memory.trackingAllocationSites = true;
88 Cu.evalInSandbox("new Object", sandbox);
89 const allocs = dbg.memory.drainAllocationsLog();
90 dbg.memory.trackingAllocationSites = false;
92 ok(allocs[0], "We should observe the allocation");
93 const { frame } = allocs[0];
95 if (sandbox !== high) {
96 ok(Cu.isXrayWrapper(frame), "`frame` should be an xray...");
97 equal(Object.prototype.toString.call(Cu.waiveXrays(frame)),
98 "[object SavedFrame]",
99 "...and that xray should wrap a SavedFrame");