Closed
Bug 1012642
Opened 11 years ago
Closed 11 years ago
Crash on Heap near [@ js::irregexp::ExecuteCode] with possible use-after-free
Categories
(Core :: JavaScript Engine, defect)
Tracking
()
VERIFIED
FIXED
mozilla32
Tracking | Status | |
---|---|---|
firefox31 | --- | unaffected |
firefox32 | --- | fixed |
firefox-esr24 | --- | unaffected |
People
(Reporter: decoder, Assigned: bhackett1024)
References
Details
(5 keywords, Whiteboard: [jsbugmon:update,bisect])
Crash Data
Attachments
(2 files)
336 bytes,
text/plain
|
Details | |
610 bytes,
patch
|
billm
:
review+
|
Details | Diff | Splinter Review |
The following testcase crashes on mozilla-central revision 41a54c8add09 (run with --fuzzing-safe --ion-eager):
var gTestcases = new Array();
function TestCase(e, a) {
this.passed = getTestCaseResult();
gTestcases[gTc++] = this;
}
TestCase.prototype.dump = function() { toPrinted() };
function toPrinted(value) {
value = String(value);
value = value.replace(/\\n/g, 'NL').replace(/\\r/g, 'CR').replace(/[^\x20-\x7E]+/g, escapeString);
}
function escapeString (str) {}
function reportCompare (e, a) {
toPrinted(e);
toPrinted(a);
new TestCase();
}
function getTestCaseResult() dump = (function () {});
for ( gTc=0; gTc < gTestcases.length; gTc++ ) {}
function jsTestDriverEnd() {
try {
foo();
} catch(ex) {}
for (var i = 0; i < gTestcases.length; i++)
gTestcases[i].dump();
}
reportCompare('', '');
function callback(obj) {}
setObjectMetadataCallback(callback);
gczeal(8);
reportCompare(true, '');
function test2() {
jsTestDriverEnd();
} test2();
Reporter | ||
Comment 1•11 years ago
|
||
Reporter | ||
Comment 2•11 years ago
|
||
Crash trace:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff595b7f0 in ?? ()
#0 0x00007ffff595b7f0 in ?? ()
#1 0x0000000000515179 in js::irregexp::ExecuteCode (cx=<optimized out>, codeBlock=<optimized out>, chars=<optimized out>, start=<optimized out>, length=<optimized out>, matches=<optimized out>) at irregexp/RegExpEngine.cpp:1665
#2 0x00000000009afdf4 in js::RegExpShared::execute (this=0x18e74f0, cx=0x180e340, chars=0x7ffff581b608 u"undefined", length=9, lastIndex=0x7fffffff82e0, matches=...) at vm/RegExpObject.cpp:707
#3 0x00000000008eb108 in DoMatchForReplaceGlobal (rdata=..., re=..., linearStr=..., res=0x18ef8e0, cx=0x180e340) at jsstr.cpp:2315
#4 StrReplaceRegExp (cx=0x180e340, rdata=..., rval=...) at jsstr.cpp:2954
#5 0x00000000008ec461 in str_replace_regexp (rdata=..., cx=0x180e340, args=...) at jsstr.cpp:2986
#6 js::str_replace (cx=0x180e340, argc=<optimized out>, vp=<optimized out>) at jsstr.cpp:3213
#7 0x00007ffff6bd0544 in ?? ()
rax 0xf581b61a 140737312306714
=> 0x7ffff595b7f0: cmpb $0x0,0x7ffff595(%rax)
On 32 bit, I also saw a trace like this earlier:
Program received signal SIGSEGV, Segmentation fault.
0x4b4b4b4b in ?? ()
(gdb) bt 32
#0 0x4b4b4b4b in ?? ()
#1 0x081026fb in js::irregexp::ExecuteCode (cx=0x91ff810, codeBlock=0xf6940920, chars=0xf6812e68 u"undefined", start=0, length=9, matches=0xffff9c4c)
at irregexp/RegExpEngine.cpp:1665
#2 0x084ad75f in js::RegExpShared::execute (this=0x92be4e0, cx=0x91ff810, chars=0xf6812e68 u"undefined", length=9, lastIndex=0xffff9c98, matches=...)
at vm/RegExpObject.cpp:707
#3 0x0841604c in DoMatchForReplaceGlobal (rdata=..., re=..., linearStr=..., res=0x92b3d20, cx=0x91ff810) at jsstr.cpp:2315
#4 StrReplaceRegExp (cx=0x91ff810, rdata=..., rval=...) at jsstr.cpp:2954
#5 0x08417c6d in str_replace_regexp (rdata=..., args=..., cx=0x91ff810) at jsstr.cpp:2986
#6 js::str_replace (cx=0x91ff810, argc=2, vp=0xffff9f4c) at jsstr.cpp:3213
#7 0xf7aeecc4 in ?? ()
#8 0x092fafc0 in ?? ()
#9 0xf7ae56ff in ?? ()
This is sec-critical because it jumps to a poison pattern 0x4b4b4b4b. Jan mentioned this could be a use-after-free. Likely a regression from the irregexp landing, not sure why we didn't pick this up during the fuzzing review.
status-firefox32:
--- → affected
Flags: needinfo?(bhackett1024)
Keywords: sec-critical
Whiteboard: [jsbugmon:update,bisect]
Updated•11 years ago
|
Group: javascript-core-security
Assignee | ||
Comment 3•11 years ago
|
||
This is something I noticed earlier today while trying to fix bug 1010441. The existing code is missing a read barrier when a RegExpShared is copied from one RegExpObject to another during cloning. There is a window where the RegExpShared is held live on the stack (via RegExpGuard) but hasn't been copied to the new object (which will trigger a barrier via prepareForUse()). If a GC is finished (and wasn't started) in this window then the contents of the RegExpShared will not have been traced even though it is kept alive by the RegExpGuard.
This didn't cause problems with yarr because in that case the RegExpShared only holds a reference on a JSAtom* which is also a property of the RegExpObject, but now the RegExpShared is the only object pointing to its JitCode*.
Attachment #8425827 -
Flags: review?(wmccloskey)
Flags: needinfo?(bhackett1024)
Assignee | ||
Updated•11 years ago
|
Assignee: nobody → bhackett1024
Updated•11 years ago
|
Keywords: csectype-uaf
Updated•11 years ago
|
Attachment #8425827 -
Flags: review?(wmccloskey) → review+
Assignee | ||
Comment 4•11 years ago
|
||
Comment 5•11 years ago
|
||
Status: NEW → RESOLVED
Closed: 11 years ago
Flags: in-testsuite?
Resolution: --- → FIXED
Target Milestone: --- → mozilla32
Reporter | ||
Updated•11 years ago
|
Status: RESOLVED → VERIFIED
Reporter | ||
Comment 6•11 years ago
|
||
JSBugMon: This bug has been automatically verified fixed.
Updated•11 years ago
|
Group: javascript-core-security
Updated•11 years ago
|
Group: core-security
You need to log in
before you can comment on or make changes to this bug.
Description
•