Closed Bug 1828396 Opened 8 months ago Closed 8 months ago

Assertion failure: slots == calculateDynamicSlots(), at vm/JSObject-inl.h:45 with Debugger and OOM

Categories

(Core :: JavaScript Engine, defect, P1)

x86_64
Linux
defect

Tracking

()

VERIFIED FIXED
114 Branch
Tracking Status
firefox-esr102 --- unaffected
firefox112 --- unaffected
firefox113 --- unaffected
firefox114 --- verified

People

(Reporter: decoder, Assigned: jonco)

References

(Regression)

Details

(Keywords: assertion, regression, testcase, Whiteboard: [bugmon:update,bisected,confirmed])

Attachments

(3 files)

The following testcase crashes on mozilla-central revision 20230415-c061ec6c908e (debug build, run with --fuzzing-safe --ion-offthread-compile=off):

a = `
  fullcompartmentchecks(true);
  oomTest(Debugger)
`.split('\n')
c = "";
while (true) {
    d = a.shift()
    if (d == null) break;
    c += d
    e(c);
    function e(f) {
        try {
            evaluate(f);
        } catch {}
    }
}

Backtrace:

received signal SIGSEGV, Segmentation fault.
#0  0x0000555556dcff56 in js::NativeObject::numDynamicSlots() const ()
#1  0x0000555556f9a838 in js::NativeObject::slotInRange(unsigned int, js::NativeObject::SentinelAllowed) const ()
#2  0x0000555556f4a8ed in JSObject::traceChildren(JSTracer*) ()
#3  0x00005555576777fb in JS::TraceChildren(JSTracer*, JS::GCCellPtr) ()
#4  0x00005555575b8a85 in js::gc::GCRuntime::checkForCompartmentMismatches() ()
#5  0x00005555575bd4a1 in js::gc::GCRuntime::endPreparePhase(JS::GCReason) ()
#6  0x00005555575c3887 in js::gc::GCRuntime::incrementalSlice(js::SliceBudget&, JS::GCReason, bool) ()
#7  0x00005555575c6e98 in js::gc::GCRuntime::gcCycle(bool, js::SliceBudget const&, JS::GCReason) ()
#8  0x00005555575c8044 in js::gc::GCRuntime::collect(bool, js::SliceBudget const&, JS::GCReason) ()
#9  0x0000555557593d7a in js::gc::GCRuntime::gc(JS::GCOptions, JS::GCReason) ()
#10 0x000055555704c4c5 in JSRuntime::destroyRuntime() ()
#11 0x0000555556efaee5 in js::DestroyContext(JSContext*) ()
#12 0x0000555556b6ba74 in main ()
rax	0x55555575a61a	93824994354714
rbx	0x0	0
rcx	0x55555830eb58	93825040182104
rdx	0x0	0
rsi	0x7ffff7105770	140737338431344
rdi	0x7ffff7104540	140737338426688
rbp	0x7fffffffd7a0	140737488344992
rsp	0x7fffffffd780	140737488344960
r8	0x7ffff7105770	140737338431344
r9	0x7ffff7f9a840	140737353721920
r10	0x2	2
r11	0x0	0
r12	0x10	16
r13	0x12	18
r14	0x2f4c62a687b0	52005119100848
r15	0x12	18
rip	0x555556dcff56 <js::NativeObject::numDynamicSlots() const+262>
=> 0x555556dcff56 <_ZNK2js12NativeObject15numDynamicSlotsEv+262>:	movl   $0x2d,0x0
   0x555556dcff61 <_ZNK2js12NativeObject15numDynamicSlotsEv+273>:	callq  0x555556c0272b <abort>
Attached file Testcase

Looks like this managed to hit this previously untested error path, where we fail to allocate the initial dynamic slots for a debugger instance object. The half-initialized object is never used for anything, but it was pre-tenured, so we see it when walking the arenas in checkForCompartmentMismatches. We trigger an assertion because the capacity in the slots header is 0 (because of this line), but calculateDynamicSlots expects the capacity to be at least SLOT_CAPACITY_MIN.

Jon, it looks like you just rewrote some of this code. Do you have thoughts on the right way to fix it?

Flags: needinfo?(jcoppeard)
Assignee: nobody → jcoppeard
Flags: needinfo?(jcoppeard)
Regressed by: 1827918

Set release status flags based on info from the regressing bug 1827918

(In reply to Iain Ireland [:iain] from comment #3)
Yes, this was caused by my change to object initialization last week. I'll look into it.

Severity: -- → S3
Priority: -- → P1

Verified bug as reproducible on mozilla-central 20230418091934-41551018c977.
The bug appears to have been introduced in the following build range:

Start: cab026b2210bccff8410a33c6c81d2c035b7b482 (20230414092130)
End: 179b8c4df1adc1335fd4cf6bc485427f3f0ac5d8 (20230414094150)
Pushlog: https://hg.mozilla.org/integration/autoland/pushloghtml?fromchange=cab026b2210bccff8410a33c6c81d2c035b7b482&tochange=179b8c4df1adc1335fd4cf6bc485427f3f0ac5d8

Whiteboard: [bugmon:update,bisect] → [bugmon:update,bisected,confirmed]

Ideally we'd make the object's state consistent if we fail to allocate dynamic
slots, but that's inconvient here because it could require allocating a shape
to match the reduced slot span.

Instead, check for partially initialized objects in the only place we encounter
them which is in the GC's compartment checking.

Pushed by jcoppeard@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/5beb3159e6ff
Check for partially initialized objects in GC compartment checks r=jandem
Status: NEW → RESOLVED
Closed: 8 months ago
Resolution: --- → FIXED
Target Milestone: --- → 114 Branch

Verified bug as fixed on rev mozilla-central 20230419214510-1be4e6b8f5cb.
Removing bugmon keyword as no further action possible. Please review the bug and re-add the keyword for further analysis.

Status: RESOLVED → VERIFIED
Keywords: bugmon
You need to log in before you can comment on or make changes to this bug.