Assertion failure: addr % Cell::CellSize == 0, at ../../jsgc.h:859 or Crash [@ js::gc::Cell::compartment]

VERIFIED FIXED in Firefox 15



7 years ago
6 years ago


(Reporter: decoder, Assigned: billm)


(Blocks: 1 bug, 4 keywords)

assertion, crash, sec-critical, testcase
Dependency tree / graph
Bug Flags:
in-testsuite +

Firefox Tracking Flags

(firefox12 unaffected, firefox13- affected, firefox14- affected, firefox15- fixed, firefox-esr10 unaffected)


(Whiteboard: [sg:critical] js-triage-needed[advisory-tracking+], crash signature)


(1 attachment)



7 years ago
The following test asserts/crashes on mozilla-central revision 75c7378c87b6 (options -m -n -a):

try { jsTestDriverEnd(); } catch(exc1) {}
for(var i=0; i<3; i++) {\
    var obj = { first: 'first', second: 'second' };\
    for (var elem in obj) {}\

Backtrace in debug build after stepping through assertion:

Program received signal SIGSEGV, Segmentation fault.
0x0804c7cd in js::gc::Cell::compartment (this=0xdadadada) at ../../jsgc.h:984
984         return arenaHeader()->compartment;
(gdb) bt 8
#0  0x0804c7cd in js::gc::Cell::compartment (this=0xdadadada) at ../../jsgc.h:984
#1  0x0811e8f5 in js::gc::CheckMarkedThing<js::types::TypeObject> (trc=0x85fe540, thing=0xdadadada) at /srv/repos/mozilla-central/js/src/jsgcmark.cpp:80
#2  0x0811c888 in js::gc::MarkInternal<js::types::TypeObject> (trc=0x85fe540, thingp=0xf750af24) at /srv/repos/mozilla-central/js/src/jsgcmark.cpp:102
#3  0x0811bf41 in js::gc::Mark<js::types::TypeObject> (trc=0x85fe540, thing=0xf750af24, name=0x845dbdc "type") at /srv/repos/mozilla-central/js/src/jsgcmark.cpp:141
#4  0x08117074 in js::gc::MarkTypeObject (trc=0x85fe540, thing=0xf750af24, name=0x845dbdc "type") at /srv/repos/mozilla-central/js/src/jsgcmark.cpp:217
#5  0x0828cf0d in js::ObjectImpl::markChildren (this=0xf750af20, trc=0x85fe540) at /srv/repos/mozilla-central/js/src/vm/ObjectImpl.cpp:157
#6  0x081189db in js::gc::MarkChildren (trc=0x85fe540, obj=0xf750af20) at /srv/repos/mozilla-central/js/src/jsgcmark.cpp:675
#7  0x08119fa2 in js::TraceChildren (trc=0x85fe540, thing=0xf750af20, kind=JSTRACE_OBJECT) at /srv/repos/mozilla-central/js/src/jsgcmark.cpp:1160
(More stack frames follow...)
(gdb) x /i $pc
=> 0x804c7cd <js::gc::Cell::compartment() const+17>:    mov    (%eax),%eax
(gdb) info reg eax
eax            0xdadad000       -623194112

Assuming s-s and sg:critical due to use-after-free condition.
Does this affect ESR-10 or Firefox 12?
status-firefox15: --- → affected
tracking-firefox15: --- → +
I'm quite sure this is Linux-only.

autoBisect shows this is probably related to the following changeset:

The first bad revision is:
changeset:   86651:dc0f6ad7eff3
user:        Bill McCloskey
date:        Fri Feb 10 18:32:08 2012 -0800
summary:     Bug 723313 - Stop using conservative stack scanner for VM stack marking (r=luke,bhackett)

Marking flags based on regression window.
Blocks: 723313
status-firefox-esr10: --- → unaffected
status-firefox12: --- → unaffected
status-firefox13: --- → affected
status-firefox14: --- → affected
tracking-firefox13: --- → ?
tracking-firefox14: --- → ?
tracking-firefox13: ? → +
tracking-firefox14: ? → +
Created attachment 620419 [details] [diff] [review]

Here's what seems to be happening. We partially execute a function in the interpreter, and then we enter the methodjit at a loop edge. At this point, the stack pointer has some value, say sp_loop. We finish executing the method in the methodjit. Inside the methodjit, the stack pointer decreases to some other value, sp_base. At that point we GC and the pointers in between sp_base and sp_loop are not marked.

We return to the methodjit and end up throwing in the middle of an op (I think GETGNAME). We then return to the interpreter. When we do so, we repoint the registers to their old location, which still has sp = sp_loop. Then we return to the interpreter, which quickly exits. Upon exiting from the interpreter, we call the write barrier verifier. It tries to trace through one of the pointers between sp_base and sp_loop (which it thinks is the correct stack pointer) and dies.

This patch is from Luke. It tries to ensure that all the FrameRegs are correct on all paths that exit the methodjit. I'm not entirely sure if there's a real, exploitable problem here. If we hadn't invoked the write barrier verifier, then we would have popped the regs eventually and everything would have been fine. However, it looks like we don't pop the regs on some return paths, so maybe that's unsafe. I don't know this code well at all.
Assignee: general → wmccloskey
Attachment #620419 - Flags: review?(bhackett1024)
Attachment #620419 - Flags: review?(bhackett1024) → review+
Last Resolved: 7 years ago
Resolution: --- → FIXED

Comment 6

7 years ago
JSBugMon: This bug has been automatically verified fixed.


7 years ago
Will this patch apply as-is to beta, aurora, and ESR, or will you need a new patch? Please request branch approvals when this is ready to go in.
status-firefox15: affected → fixed
This only seems to affect the barrier verifier, so it's debug-only. We don't need the fix on branches.
Group: core-security
tracking-firefox13: + → -
tracking-firefox14: + → -
tracking-firefox15: + → -
Whiteboard: [sg:critical] js-triage-needed → [sg:critical] js-triage-needed[advisory-tracking+]

Comment 9

6 years ago
A testcase for this bug was automatically identified at js/src/jit-test/tests/basic/bug749039.js.
Flags: in-testsuite+
You need to log in before you can comment on or make changes to this bug.