Last Comment Bug 749039 - Assertion failure: addr % Cell::CellSize == 0, at ../../jsgc.h:859 or Crash [@ js::gc::Cell::compartment]
: Assertion failure: addr % Cell::CellSize == 0, at ../../jsgc.h:859 or Crash [...
Status: VERIFIED FIXED
[sg:critical] js-triage-needed[adviso...
: assertion, crash, sec-critical, testcase
Product: Core
Classification: Components
Component: JavaScript Engine (show other bugs)
: Trunk
: x86 Linux
: -- critical (vote)
: mozilla15
Assigned To: Bill McCloskey (:billm)
:
: Jason Orendorff [:jorendorff]
Mentors:
Depends on:
Blocks: langfuzz 723313
  Show dependency treegraph
 
Reported: 2012-04-25 17:46 PDT by Christian Holler (:decoder)
Modified: 2013-01-14 08:20 PST (History)
8 users (show)
choller: in‑testsuite+
See Also:
Crash Signature:
QA Whiteboard:
Iteration: ---
Points: ---
Has Regression Range: ---
Has STR: ---
unaffected
-
affected
-
affected
-
fixed
unaffected


Attachments
patch (4.54 KB, patch)
2012-05-02 12:12 PDT, Bill McCloskey (:billm)
bhackett1024: review+
Details | Diff | Splinter Review

Description Christian Holler (:decoder) 2012-04-25 17:46:39 PDT
The following test asserts/crashes on mozilla-central revision 75c7378c87b6 (options -m -n -a):


gczeal(4);
try { jsTestDriverEnd(); } catch(exc1) {}
evaluate("\
schedulegc(10);\
for(var i=0; i<3; i++) {\
    var obj = { first: 'first', second: 'second' };\
    for (var elem in obj) {}\
    x.push(count);\
}\
");


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.
Comment 1 Daniel Veditz [:dveditz] 2012-04-26 13:23:09 PDT
Does this affect ESR-10 or Firefox 12?
Comment 2 Gary Kwong [:gkw] [:nth10sd] 2012-04-26 16:05:36 PDT
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.
Comment 3 Bill McCloskey (:billm) 2012-05-02 12:12:04 PDT
Created attachment 620419 [details] [diff] [review]
patch

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.
Comment 5 Bill McCloskey (:billm) 2012-05-07 18:10:27 PDT
https://hg.mozilla.org/mozilla-central/rev/0e883cf61970
Comment 6 Christian Holler (:decoder) 2012-05-07 18:44:55 PDT
JSBugMon: This bug has been automatically verified fixed.
Comment 7 Daniel Veditz [:dveditz] 2012-05-10 13:54:29 PDT
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.
Comment 8 Bill McCloskey (:billm) 2012-05-10 14:07:36 PDT
This only seems to affect the barrier verifier, so it's debug-only. We don't need the fix on branches.
Comment 9 Christian Holler (:decoder) 2013-01-14 08:20:48 PST
A testcase for this bug was automatically identified at js/src/jit-test/tests/basic/bug749039.js.

Note You need to log in before you can comment on or make changes to this bug.