Open Bug 2068419 Opened 2 months ago Updated 2 months ago

Assertion failure: !r.empty() / OOB index into FlowGraphSummary in [@ js::DebuggerScript::GetOffsetLocationMatcher::match] with saturated column numbers

Categories

(Core :: JavaScript: Debugger API, defect, P3)

defect

Tracking

()

UNCONFIRMED

People

(Reporter: bugmon, Unassigned)

References

(Blocks 1 open bug)

Details

(Keywords: assertion, testcase)

Attachments

(4 files)

DebuggerScript::GetOffsetLocationMatcher::match (js/src/debugger/Script.cpp:1359-1363) walks the BytecodeRangeWithPosition forward with no !r.empty() guard, assuming the trailing RetRval is always an entry point; that assumption fails when a script is compiled with a start columnNumber within ~14 units of JS::LimitedColumnNumberOneOrigin::Limit, because the return and closing } columns both clamp to the limit so FunctionScriptEmitter::emitEndBody's updateSourceCoordNotes(bodyEnd) emits no ColSpan note for that op. Calling Debugger.Script.prototype.getOffsetLocation() on the trailing RetRval's offset then pops past the end of the bytecode and indexes flowData[script->length()] — MOZ_ASSERT(!r.empty()) in debug, MOZ_CRASH(ElementAt(aIndex = 3, aLength = 3)) from mozilla::Vector::operator[] in opt.

Exploit Chain

  1. Privileged (shell or chrome) code creates a debuggee global and attaches a Debugger to it.
  2. It evaluates function f(){ return 1 } in the debuggee with columnNumber >= 0x3FFFFFF1, so the columns of return and the closing } both clamp to 1073741823 and the emitter emits no source note for the trailing RetRval at pc 2 (the disassembly shows only a breakpoint-step-sep note at pc 0, versus a colspan/breakpoint note at pc 2 for ordinary columns).
  3. It calls Debugger.Script.prototype.getOffsetLocation(2) on f's script.
  4. GetOffsetLocationMatcher::match finds pc 2 is neither an entry point nor has a single incoming edge, pops past the end of the bytecode, and indexes flowData[script->length()].
  5. Debug build: Assertion failure: !r.empty(), at js/src/debugger/Script.cpp:1362. Opt build: MOZ_CRASH(ElementAt(aIndex = 3, aLength = 3)) from mozilla::Vector::operator[] — process abort.

Affected Code

Steps to Reproduce

  1. Ensure the tree is clean (git -C /firefox status shows no changes).
  2. Build the SpiderMonkey debug shell: build_firefox(firefox_dir='/firefox', mozconfig_path='/app/mozconfigs/mozconfig.js.linux.debug').
  3. Run the testcase with js_shell_evaluator against /firefox/obj-js-debug/dist/bin/js (the evaluator adds --fuzzing-safe; no other flags):
  4. var g = newGlobal({newCompartment: true});
    var dbg = new Debugger(g);
    g.evaluate("function f(){ return 1 }", {columnNumber: 0x3FFFFFFE});
    for (var s of dbg.findScripts()) {
    for (var off = 0; off < 64; off++) {
    try { s.getOffsetLocation(off); } catch (e) {}
    }
    }
  5. Observe Assertion failure: !r.empty(), at js/src/debugger/Script.cpp:1362 in js::DebuggerScript::GetOffsetLocationMatcher::match.
  6. Optionally run the same testcase against the ASAN fuzzing shell (/app/mozconfigs/mozconfig.linux.asan.fuzzing, /firefox/obj-firefox-asan/dist/bin/js) to observe MOZ_CRASH(ElementAt(aIndex = 3, aLength = 3)) from mozilla::Vector::operator[] at Script.cpp:1360.

Security Impact

  • Severity: Low
  • Attacker capability: Code with access to the Debugger API can abort the process by asking for the offset location of the trailing RetRval of a function compiled with a near-limit column number. In debug builds this is a MOZ_ASSERT failure; in release builds the out-of-bounds Vector index is caught by the release-mode bounds check and results in a controlled MOZ_CRASH. No memory disclosure or corruption was demonstrated.
  • Preconditions: Caller must be able to use the SpiderMonkey Debugger API (JS shell or privileged chrome code); the script must be compiled with a start columnNumber within about 14 UTF-16 units of JS::LimitedColumnNumberOneOrigin::Limit (2^30-1), e.g. via evaluate(..., {columnNumber: 0x3FFFFFF1}) or higher.

The full analysis report is attached (analysis.md).

Attached patch fix.patch — — Splinter Review
Attached file crash_stack.txt —
Attached file testcase.js —
Attached file analysis.md —

This bug was filed automatically by an AI-powered security testing tool. The analysis, testcase, and any suggested patches were generated by an AI model and have NOT been verified by a human.

Please review all details carefully before triaging. The issue was confirmed by an independent verifier, but for non-ASAN issues, the verifier has been made less strict. Additionally, the root cause analysis and suggested fix may contain errors.

Group: core-security → javascript-core-security
Blocks: sm-security
Severity: -- → S3
Priority: -- → P3
Group: javascript-core-security
Keywords: sec-other
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: