Open Bug 1844894 Opened 2 years ago Updated 2 years ago

Assertion failure: cx->realm()->isDebuggee()

Categories

(Core :: JavaScript Engine, defect, P3)

Firefox 115
defect

Tracking

()

People

(Reporter: anbu1024.me, Unassigned)

References

(Blocks 1 open bug)

Details

Steps to reproduce:

SpiderMonkey version:
commit 920be8b5eee004fc10a2785fab49b860be4d4ba3

SpiderMonkey build cmd:

/bin/sh ../../gecko-dev/js/src/configure --enable-debug --disable-optimize --disable-shared-js --disable-tests

Exec:

./js ./test.js

Test Case:

for (let a = 8, b = 10;
    (() => {
        const x = a < b;
        this.newGlobal(a, this, b, x);
        return x;
    })();
    (() => {b--;})()
    ) 
{}

async function foo(a) {
    return a;
}

const x = foo().then(foo);

for (let i = 0, j = 10; i !== j;
    (() => {
        function zoo(a) {
            async function* bob() {
                return a;
            }
            bob().next();
        }
        new zoo(x);
        j--;
    })()) {
}

const v88 = this.Debugger;

const y = this.wasmIntrinsicI8VecMul(foo, this);

function alice() {
    const tom = v88();

    for (let i = 0, j = 10;
        (() => {
            return y in arguments;

        })();
        ) {
    }
    return tom.findAllGlobals(x, tom);
}


Object.defineProperty(y, "constructor", { writable: true, configurable: true, value: alice });

const z = y.constructor;

z()[1].makeDebuggeeValue(x).getPromiseReactions();

Actual results:

Error msg:

Assertion failure: cx->realm()->isDebuggee(), at gecko-dev/js/src/debugger/DebugScript.cpp:305

Thank you for reporting!

Here's reduced testcase:

var p = new Promise(_ => {});
async function f() {
  await p;
}
f();

const dbg = new Debugger();
const globals = dbg.findAllGlobals();
const g = globals[0];
const q = g.makeDebuggeeValue(p);
q.getPromiseReactions();

So, what's happening here is that, Debugger().findAllGlobals() returns the current global, which is not debuggee, wrapped by Debugger.Object.
But getPromiseReactions assumes the wrapped value belongs to debuggee global.

This is because, the globals returned by findAllGlobals are supposed to be either added to debugger immediately with addDebuggee, or the reference gets discarded.

In tree, findAllGlobals is called only in the following places:

https://searchfox.org/mozilla-central/rev/920be8b5eee004fc10a2785fab49b860be4d4ba3/devtools/server/actors/targets/content-process.js#67-68

this.makeDebugger = makeDebugger.bind(null, {
  findDebuggees: dbg => dbg.findAllGlobals(),

https://searchfox.org/mozilla-central/rev/920be8b5eee004fc10a2785fab49b860be4d4ba3/devtools/server/actors/targets/parent-process.js#60-61

this.makeDebugger = makeDebugger.bind(null, {
  findDebuggees: dbg => dbg.findAllGlobals(),

https://searchfox.org/mozilla-central/rev/920be8b5eee004fc10a2785fab49b860be4d4ba3/devtools/server/actors/targets/webextension.js#145-147

this.makeDebugger = makeDebugger.bind(null, {
  findDebuggees: dbg => {
    return dbg.findAllGlobals().filter(this._shouldAddNewGlobalAsDebuggee);

and globals returned there are immediately passed to addDebuggee.
So the case doesn't happen.

https://searchfox.org/mozilla-central/rev/920be8b5eee004fc10a2785fab49b860be4d4ba3/devtools/server/actors/utils/make-debugger.js#59-62,84-85,107-113

module.exports = function makeDebugger({
  findDebuggees,
  shouldAddNewGlobalAsDebuggee,
} = {}) {
...
    for (const global of findDebuggees(this)) {
      safeAddDebuggee(this, global);
...
function safeAddDebuggee(dbg, global) {
  let globalDO;
  try {
    globalDO = dbg.addDebuggee(global);
  } catch (e) {
    // Ignoring attempt to add the debugger's compartment as a debuggee.
    return;

Also, given Debugger is not exposed to web content, this issue is shell-only.

Blocks: js-debugger
Severity: -- → S3
Status: UNCONFIRMED → NEW
Ever confirmed: true
Priority: -- → P3
Severity: S3 → S4
You need to log in before you can comment on or make changes to this bug.