diff options
Diffstat (limited to 'js/xpconnect/tests/unit/test_xray_SavedFrame-02.js')
-rw-r--r-- | js/xpconnect/tests/unit/test_xray_SavedFrame-02.js | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/js/xpconnect/tests/unit/test_xray_SavedFrame-02.js b/js/xpconnect/tests/unit/test_xray_SavedFrame-02.js new file mode 100644 index 0000000000..e9b5752044 --- /dev/null +++ b/js/xpconnect/tests/unit/test_xray_SavedFrame-02.js @@ -0,0 +1,71 @@ +// Test calling SavedFrame getters across wrappers from privileged and +// un-privileged globals. + +const {addDebuggerToGlobal} = ChromeUtils.importESModule("resource://gre/modules/jsdebugger.sys.mjs"); +addDebuggerToGlobal(globalThis); + +const lowP = Services.scriptSecurityManager.createNullPrincipal({}); +const highP = Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal); + +const low = new Cu.Sandbox(lowP); +const high = new Cu.Sandbox(highP); + +function run_test() { + // Privileged compartment accessing unprivileged stack. + high.stack = getSavedFrameInstanceFromSandbox(low); + Cu.evalInSandbox("this.parent = stack.parent", high); + Cu.evalInSandbox("this.asyncParent = stack.asyncParent", high); + Cu.evalInSandbox("this.source = stack.source", high); + Cu.evalInSandbox("this.functionDisplayName = stack.functionDisplayName", high); + + // Un-privileged compartment accessing privileged stack. + low.stack = getSavedFrameInstanceFromSandbox(high); + try { + Cu.evalInSandbox("this.parent = stack.parent", low); + } catch (e) { } + try { + Cu.evalInSandbox("this.asyncParent = stack.asyncParent", low); + } catch (e) { } + try { + Cu.evalInSandbox("this.source = stack.source", low); + } catch (e) { } + try { + Cu.evalInSandbox("this.functionDisplayName = stack.functionDisplayName", low); + } catch (e) { } + + // Privileged compartment accessing privileged stack. + let stack = getSavedFrameInstanceFromSandbox(high); + let parent = stack.parent; + let asyncParent = stack.asyncParent; + let source = stack.source; + let functionDisplayName = stack.functionDisplayName; + + ok(true, "Didn't crash"); +} + +// Get a SavedFrame instance from inside the given sandbox. +// +// We can't use Cu.getJSTestingFunctions().saveStack() because Cu isn't +// available to sandboxes that don't have the system principal. The easiest way +// to get the SavedFrame is to use the Debugger API to track allocation sites +// and then do an allocation. +function getSavedFrameInstanceFromSandbox(sandbox) { + const dbg = new Debugger(sandbox); + + dbg.memory.trackingAllocationSites = true; + Cu.evalInSandbox("(function iife() { return new RegExp }())", sandbox); + const allocs = dbg.memory.drainAllocationsLog().filter(e => e.class === "RegExp"); + dbg.memory.trackingAllocationSites = false; + + ok(allocs[0], "We should observe the allocation"); + const { frame } = allocs[0]; + + if (sandbox !== high) { + ok(Cu.isXrayWrapper(frame), "`frame` should be an xray..."); + equal(Object.prototype.toString.call(Cu.waiveXrays(frame)), + "[object SavedFrame]", + "...and that xray should wrap a SavedFrame"); + } + + return frame; +} |