tor-browser

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

test_xray_SavedFrame.js (3391B)


      1 // Bug 1117242: Test calling SavedFrame getters from globals that don't subsume
      2 // that frame's principals.
      3 
      4 const {addDebuggerToGlobal} = ChromeUtils.importESModule("resource://gre/modules/jsdebugger.sys.mjs");
      5 addDebuggerToGlobal(globalThis);
      6 
      7 const lowP = Services.scriptSecurityManager.createNullPrincipal({});
      8 const midP = [lowP, "http://other.com"];
      9 const highP = Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal);
     10 
     11 const low  = new Cu.Sandbox(lowP);
     12 const mid  = new Cu.Sandbox(midP);
     13 const high = new Cu.Sandbox(highP);
     14 
     15 function run_test() {
     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):
     20  //
     21  //     low.lowF -> mid.midF -> high.highF -> high.saveStack
     22  //
     23  // Where high.saveStack gets monkey patched to create stacks in each of our
     24  // sandboxes.
     25 
     26  Cu.evalInSandbox("function highF() { return saveStack(); }", high);
     27 
     28  mid.highF = () => high.highF();
     29  Cu.evalInSandbox("function midF() { return highF(); }", mid);
     30 
     31  low.midF = () => mid.midF();
     32  Cu.evalInSandbox("function lowF() { return midF(); }", low);
     33 
     34  const expected = [
     35    {
     36      sandbox: low,
     37      frames: ["lowF"],
     38    },
     39    {
     40      sandbox: mid,
     41      frames: ["midF", "lowF"],
     42    },
     43    {
     44      sandbox: high,
     45      frames: ["getSavedFrameInstanceFromSandbox",
     46               "saveStack",
     47               "highF",
     48               "run_test/mid.highF",
     49               "midF",
     50               "run_test/low.midF",
     51               "lowF",
     52               "run_test",
     53               "_execute_test",
     54               null],
     55    }
     56  ];
     57 
     58  for (let { sandbox, frames } of expected) {
     59    high.saveStack = function saveStack() {
     60      return getSavedFrameInstanceFromSandbox(sandbox);
     61    };
     62 
     63    const xrayStack = low.lowF();
     64    equal(xrayStack.functionDisplayName, "getSavedFrameInstanceFromSandbox",
     65          "Xrays should always be able to see everything.");
     66 
     67    let waived = Cu.waiveXrays(xrayStack);
     68    do {
     69      ok(frames.length,
     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;
     74    } while (waived);
     75  }
     76 }
     77 
     78 // Get a SavedFrame instance from inside the given sandbox.
     79 //
     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);
     86 
     87  dbg.memory.trackingAllocationSites = true;
     88  Cu.evalInSandbox("new Object", sandbox);
     89  const allocs = dbg.memory.drainAllocationsLog();
     90  dbg.memory.trackingAllocationSites = false;
     91 
     92  ok(allocs[0], "We should observe the allocation");
     93  const { frame } = allocs[0];
     94 
     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");
    100  }
    101 
    102  return frame;
    103 }