Closed
Bug 701332
Opened 13 years ago
Closed 13 years ago
SIGTRAP on heap (in JSC::Yarr::execute code) with use after free
Categories
(Core :: JavaScript Engine, defect)
Tracking
()
VERIFIED
FIXED
mozilla11
Tracking | Status | |
---|---|---|
firefox8 | - | unaffected |
firefox9 | + | unaffected |
firefox10 | + | fixed |
firefox11 | + | verified |
firefox12 | --- | fixed |
status1.9.2 | --- | unaffected |
People
(Reporter: decoder, Assigned: cdleary)
References
Details
(Keywords: crash, regression, testcase, Whiteboard: [sg:critical][qa+])
Attachments
(2 files)
1.76 KB,
patch
|
Waldo
:
review+
asa
:
approval-mozilla-aurora+
|
Details | Diff | Splinter Review |
30.54 KB,
patch
|
Waldo
:
review+
|
Details | Diff | Splinter Review |
The following test crashes on mozilla-central revision c60535115ea1 (options -m -n):
gczeal(2);
test();
function test() {
function t(o, proplist) {
var props=proplist.split(/\s+/g);
};
t({ bar: 123, baz: 123, quux: 123 }, 'bar baz quux');
( test(), this )(( "7.4.2-6-n" ) , actual, summary + ' : nonjit');
}
Backtrace from valgrind:
==30698== Invalid read of size 4
==30698== at 0x651B7C: js::RegExpPrivate::pairCount() const (RegExpObject.h:357)
==30698== by 0x64FDCE: js::RegExpPrivate::execute(JSContext*, unsigned short const*, unsigned long, unsigned long*, js::LifoAllocScope&, js::MatchPairs**) (RegExpObject.cpp:191)
==30698== by 0x6581B0: bool ExecuteRegExpImpl<js::RegExpPrivate>(JSContext*, js::RegExpStatics*, js::RegExpPrivate*, JSLinearString*, unsigned short const*, unsigned long, unsig
ned long*, js::RegExpExecType, JS::Value*) (RegExp.cpp:135)
==30698== by 0x655B8A: js::ExecuteRegExp(JSContext*, js::RegExpStatics*, js::RegExpPrivate*, JSLinearString*, unsigned short const*, unsigned long, unsigned long*, js::RegExpExe
cType, JS::Value*) (RegExp.cpp:166)
==30698== by 0x5921B2: SplitRegExpMatcher::operator()(JSContext*, JSLinearString*, unsigned long, SplitMatchResult*) (jsstr.cpp:2425)
==30698== by 0x58E98E: JSObject* SplitHelper<SplitRegExpMatcher>(JSContext*, JSLinearString*, unsigned int, SplitRegExpMatcher, js::types::TypeObject*) (jsstr.cpp:2313)
==30698== by 0x589BF0: js::str_split(JSContext*, unsigned int, JS::Value*) (jsstr.cpp:2536)
==30698== by 0x4FF690: js::CallJSNative(JSContext*, int (*)(JSContext*, unsigned int, JS::Value*), js::CallArgs const&) (jscntxtinlines.h:297)
==30698== by 0x4E0D62: js::InvokeKernel(JSContext*, js::CallArgs, js::MaybeConstruct) (jsinterp.cpp:629)
==30698== by 0x4F0D87: js::Interpret(JSContext*, js::StackFrame*, js::InterpMode) (jsinterp.cpp:3948)
==30698== by 0x4E0B16: js::RunScript(JSContext*, JSScript*, js::StackFrame*) (jsinterp.cpp:584)
==30698== by 0x4E15F8: js::ExecuteKernel(JSContext*, JSScript*, JSObject&, JS::Value const&, js::ExecuteType, js::StackFrame*, JS::Value*) (jsinterp.cpp:783)
==30698== Address 0x5e38658 is 56 bytes inside a block of size 64 free'd
==30698== at 0x4C282ED: free (vg_replace_malloc.c:366)
==30698== by 0x40382B: js_free (Utility.h:183)
==30698== by 0x4114F3: js::Foreground::free_(void*) (Utility.h:597)
==30698== by 0x41A3D3: JSRuntime::free_(void*) (jscntxt.h:770)
==30698== by 0x41A4B6: JSContext::free_(void*) (jscntxt.h:1269)
==30698== by 0x593883: void JSContext::delete_<js::RegExpPrivate>(js::RegExpPrivate*) (in /srv/repos/mozilla-central/js/src/debug64/shell/js)
==30698== by 0x5915BA: js::RegExpPrivate::decref(JSContext*) (RegExpObject-inl.h:372)
==30698== by 0x651C39: js::RegExpObject::purge(JSContext*) (RegExpObject-inl.h:132)
==30698== by 0x651C70: js::RegExpObject::finalize(JSContext*) (RegExpObject-inl.h:140)
==30698== by 0x65041A: regexp_finalize(JSContext*, JSObject*) (RegExpObject.cpp:336)
==30698== by 0x4ACF12: JSObject::finalize(JSContext*) (jsobjinlines.h:267)
==30698== by 0x4B0C69: bool js::gc::Arena::finalize<JSObject>(JSContext*, js::gc::AllocKind, unsigned long) (jsgc.cpp:302)
[ More invalid reads here ]
==30698== Process terminating with default action of signal 5 (SIGTRAP)
==30698== at 0x40392B9: ???
==30698== by 0x7242C2: JSC::Yarr::execute(JSC::Yarr::YarrCodeBlock&, unsigned short const*, unsigned int, unsigned int, int*) (YarrJIT.cpp:2461)
==30698== by 0x65288C: js::RegExpPrivateCode::execute(JSContext*, unsigned short const*, unsigned long, unsigned long, int*, unsigned long) (RegExpObject-inl.h:334)
==30698== by 0x64FE9B: js::RegExpPrivate::execute(JSContext*, unsigned short const*, unsigned long, unsigned long*, js::LifoAllocScope&, js::MatchPairs**) (RegExpObject.cpp:212)
==30698== by 0x6581B0: bool ExecuteRegExpImpl<js::RegExpPrivate>(JSContext*, js::RegExpStatics*, js::RegExpPrivate*, JSLinearString*, unsigned short const*, unsigned long, unsigned long*, js::RegExpExecType, JS::Value*) (RegExp.cpp:135)
==30698== by 0x655B8A: js::ExecuteRegExp(JSContext*, js::RegExpStatics*, js::RegExpPrivate*, JSLinearString*, unsigned short const*, unsigned long, unsigned long*, js::RegExpExecType, JS::Value*) (RegExp.cpp:166)
==30698== by 0x5921B2: SplitRegExpMatcher::operator()(JSContext*, JSLinearString*, unsigned long, SplitMatchResult*) (jsstr.cpp:2425)
==30698== by 0x58E98E: JSObject* SplitHelper<SplitRegExpMatcher>(JSContext*, JSLinearString*, unsigned int, SplitRegExpMatcher, js::types::TypeObject*) (jsstr.cpp:2313)
==30698== by 0x589BF0: js::str_split(JSContext*, unsigned int, JS::Value*) (jsstr.cpp:2536)
==30698== by 0x4FF690: js::CallJSNative(JSContext*, int (*)(JSContext*, unsigned int, JS::Value*), js::CallArgs const&) (jscntxtinlines.h:297)
==30698== by 0x4E0D62: js::InvokeKernel(JSContext*, js::CallArgs, js::MaybeConstruct) (jsinterp.cpp:629)
==30698== by 0x4F0D87: js::Interpret(JSContext*, js::StackFrame*, js::InterpMode) (jsinterp.cpp:3948)
S-s and sg:critical due to use-after-free and SIGTRAP (usually indicating that execution hit a TRAP slide which would lead to execution of random memory in optimized builds).
Assignee | ||
Comment 1•13 years ago
|
||
Fix coming up, plus a way to avoid this category of errors going forward. :-P
Assignee: general → cdleary
Whiteboard: [sg:critical] js-triage-needed → [sg:critical]
Assignee | ||
Comment 3•13 years ago
|
||
Hide RegExpPrivates from the outside world by use of an auto-refcounting matcher interface.
Attachment #573580 -
Flags: review?(jwalden+bmo)
Updated•13 years ago
|
status-firefox10:
--- → affected
status-firefox11:
--- → affected
status-firefox8:
--- → wontfix
status-firefox9:
--- → affected
tracking-firefox10:
--- → +
tracking-firefox11:
--- → +
tracking-firefox8:
--- → -
tracking-firefox9:
--- → +
Comment 4•13 years ago
|
||
Comment on attachment 573580 [details] [diff] [review]
Hide RegExpPrivates.
Review of attachment 573580 [details] [diff] [review]:
-----------------------------------------------------------------
I am a fan of not exposing RegExpPrivate.
::: js/src/builtin/RegExp.cpp
@@ +158,5 @@
> return CreateRegExpMatchResult(cx, input, chars, length, matchPairs, rval);
> }
>
> bool
> +js::ExecuteRegExp(JSContext *cx, RegExpStatics *res, RegExpMatcher *matcher, JSLinearString *input,
|matcher| should be a reference.
::: js/src/builtin/RegExp.h
@@ +63,5 @@
> const jschar *chars, size_t length,
> size_t *lastIndex, RegExpExecType type, Value *rval);
>
> bool
> +ExecuteRegExp(JSContext *cx, RegExpStatics *res, RegExpMatcher *matcher, JSLinearString *input,
Reference.
::: js/src/jsstr.cpp
@@ +1295,4 @@
>
> RegExpObject *reobj() const { return reobj_; }
>
> + RegExpMatcher *getMatcher() const {
This should return a reference and be matcher().
@@ +2401,5 @@
> * index at which a match happens.
> */
> class SplitRegExpMatcher {
> RegExpStatics *res;
> + RegExpMatcher *matcher;
Reference.
::: js/src/vm/RegExpObject-inl.h
@@ +394,5 @@
>
> +#ifdef DEBUG
> + this->~RegExpPrivate();
> + memset(this, 0xcd, sizeof(*this));
> + cx->free_(this);
We should have poisoningFree and poisoningDelete methods, that poison in debug builds. Or something. I dunno. This is fine for now.
::: js/src/vm/RegExpObject.h
@@ +162,5 @@
> inline void purge(JSContext *x);
>
> + /*
> + * Trigger an eager creation of the associated RegExpPrivate. Note
> + * that a GC may purge it away.
"away" feels redundant to me, maybe.
Attachment #573580 -
Flags: review?(jwalden+bmo) → review+
Updated•13 years ago
|
Attachment #573579 -
Flags: review?(jwalden+bmo) → review+
Assignee | ||
Comment 5•13 years ago
|
||
https://hg.mozilla.org/integration/mozilla-inbound/rev/16d8593b432a
https://hg.mozilla.org/integration/mozilla-inbound/rev/c78a8eaa8a7b
Target Milestone: --- → mozilla11
Assignee | ||
Comment 6•13 years ago
|
||
Status: NEW → ASSIGNED
Assignee | ||
Comment 7•13 years ago
|
||
https://hg.mozilla.org/mozilla-central/rev/16d8593b432a
https://hg.mozilla.org/mozilla-central/rev/c78a8eaa8a7b
https://hg.mozilla.org/mozilla-central/rev/74b1322c287e
Status: ASSIGNED → RESOLVED
Closed: 13 years ago
Resolution: --- → FIXED
Assignee | ||
Comment 8•13 years ago
|
||
Comment on attachment 573579 [details] [diff] [review]
Minimal fix.
10 is affected.
Attachment #573579 -
Flags: approval-mozilla-aurora?
Comment 9•13 years ago
|
||
Comment on attachment 573579 [details] [diff] [review]
Minimal fix.
Approving for Aurora (10)
Do we know for sure that Beta (9) is affected?
Attachment #573579 -
Flags: approval-mozilla-aurora? → approval-mozilla-aurora+
Comment 10•13 years ago
|
||
Has this landed on Aurora? Do we know if FF9 is affected?
Assignee | ||
Comment 11•13 years ago
|
||
Sorry, I failed to update this bug appropriately -- the backout from
http://hg.mozilla.org/releases/mozilla-aurora/pushloghtml?changeset=3f725329f26d
reverted lazy regexps, so Aurora is no longer affected. All extant RegExp objects hold a refcount to an eagerly-created RegExpPrivate and the RegExp object in str_split is appropriately rooted in vp[2].
Waldo, do you mind double checking me?
Comment 12•13 years ago
|
||
Just to double check, this is fixed in Firefox 11 given that the bug is marked as fixed?
Comment 13•13 years ago
|
||
Chris: comment 11 seems to be saying this bug is a regression from something, which was then backed out from Fx10 Aurora? If so please add the regression keyword and the bug number to the "Blocks" field. I think you're also saying we should set the firefox 11 status field to "fixed" and for firefox 10 to either fixed or unaffected.
What about 9?
Assignee | ||
Comment 14•13 years ago
|
||
(In reply to Daniel Veditz from comment #13)
> Chris: comment 11 seems to be saying this bug is a regression from
> something, which was then backed out from Fx10 Aurora? If so please add the
> regression keyword and the bug number to the "Blocks" field.
Done! For reference, the Fx10 Aurora backout was performed in bug 702426.
> I think you're
> also saying we should set the firefox 11 status field to "fixed" and for
> firefox 10 to either fixed or unaffected.
Fx11 is fixed by the trunk changesets given above, and Fx10 Aurora is unaffected due to the backout that I was referencing.
> What about 9?
Fx9 Beta was unaffected.
Blocks: 634654
Whiteboard: [sg:critical][qa+] → [sg:critical][qa+][regression]
Updated•13 years ago
|
Keywords: regression
Whiteboard: [sg:critical][qa+][regression] → [sg:critical][qa+]
Updated•13 years ago
|
status1.9.2:
--- → unaffected
status-firefox12:
--- → fixed
Comment 15•13 years ago
|
||
I'm trying to verify this with the Firefox 11.0b6 js-shell by copying in the following code:
gczeal(2);
test();
function test() {
function t(o, proplist) {
var props=proplist.split(/\s+/g);
};
t({ bar: 123, baz: 123, quux: 123 }, 'bar baz quux');
( test(), this )(( "7.4.2-6-n" ) , actual, summary + ' : nonjit');
}
I get the following output:
typein:1: ReferenceError: gczeal is not defined
typein:2: ReferenceError: test is not defined
Am I doing something wrong?
Comment 16•13 years ago
|
||
I got my problem sorted out -- built a debug shell from today's mozilla-beta and confirmed the test does not crash.
Verified for Firefox 11.0b6
Updated•13 years ago
|
Group: core-security
Reporter | ||
Updated•13 years ago
|
Status: RESOLVED → VERIFIED
You need to log in
before you can comment on or make changes to this bug.
Description
•