Closed
Bug 1298135
Opened 8 years ago
Closed 8 years ago
Crash [@ js::GCMarker::eagerlyMarkChildren] or Crash [@ JSString::isPermanentAtom] with use-after-free
Categories
(Core :: JavaScript Engine, defect)
Tracking
()
RESOLVED
DUPLICATE
of bug 1301343
Tracking | Status | |
---|---|---|
firefox49 | --- | unaffected |
firefox-esr45 | --- | unaffected |
People
(Reporter: decoder, Unassigned)
References
Details
(5 keywords, Whiteboard: [jsbugmon:ignore])
Crash Data
Attachments
(3 files)
The following testcase crashes on mozilla-central revision 01748a2b1a46 (build with --enable-posix-nspr-emulation --enable-valgrind --enable-gczeal --disable-tests --disable-debug --enable-optimize, run with --fuzzing-safe --thread-count=2 --disable-oom-functions --ion-eager):
See attachment.
Backtrace:
received signal SIGSEGV, Segmentation fault.
js::GCMarker::eagerlyMarkChildren (this=<optimized out>, linearStr=<optimized out>) at js/src/gc/Marking.cpp:1107
#0 js::GCMarker::eagerlyMarkChildren (this=<optimized out>, linearStr=<optimized out>) at js/src/gc/Marking.cpp:1107
#1 js::GCMarker::eagerlyMarkChildren (str=0x7ffff0ec3058, this=0x7ffff6961550) at js/src/gc/Marking.cpp:1085
#2 js::GCMarker::markAndScan<JSString> (this=this@entry=0x7ffff6961550, thing=0x7ffff0ec3058) at js/src/gc/Marking.cpp:884
#3 0x0000000000a73240 in js::GCMarker::traverse<JSString*> (thing=<optimized out>, this=0x7ffff6961550) at js/src/gc/Marking.cpp:887
#4 js::GCMarker::traverseEdge<js::ObjectGroup*, JSString> (source=0x7ffff366dac0, target=<optimized out>, this=0x7ffff6961550) at js/src/gc/Marking.cpp:946
#5 TraverseEdgeFunctor<jsid, js::ObjectGroup*>::operator()<JSString*> (this=<synthetic pointer>, s=0x7ffff366dac0, gcmarker=0x7ffff6961550, t=<optimized out>) at js/src/gc/Marking.cpp:951
#6 js::DispatchTyped<TraverseEdgeFunctor<jsid, js::ObjectGroup*>, js::GCMarker*, js::ObjectGroup*&>(TraverseEdgeFunctor<jsid, js::ObjectGroup*>, jsid&, js::GCMarker*&&, js::ObjectGroup*&) (iden=<synthetic pointer>, f=...) at /srv/jenkins/jobs/mozilla-central-build-jsshell/workspace/arch/64/compiler/gcc/sanitizer/none/type/opt/dist/include/js/Id.h:210
#7 js::GCMarker::traverseEdge<js::ObjectGroup*, jsid> (thing=..., source=0x7ffff366dac0, this=0x7ffff6961550) at js/src/gc/Marking.cpp:959
#8 js::GCMarker::lazilyMarkChildren (this=0x7ffff6961550, group=group@entry=0x7ffff366dac0) at js/src/gc/Marking.cpp:1244
#9 0x0000000000a86100 in js::GCMarker::processMarkStackTop (this=this@entry=0x7ffff6961550, budget=...) at js/src/gc/Marking.cpp:1470
#10 0x0000000000a78107 in js::GCMarker::drainMarkStack (this=this@entry=0x7ffff6961550, budget=...) at js/src/gc/Marking.cpp:1372
#11 0x0000000000783600 in js::gc::GCRuntime::drainMarkStack (this=0x7ffff695f448, sliceBudget=..., phase=<optimized out>) at js/src/jsgc.cpp:5190
#12 0x00000000007a0414 in js::gc::GCRuntime::incrementalCollectSlice (this=this@entry=0x7ffff695f448, budget=..., reason=reason@entry=JS::gcreason::DEBUG_GC, lock=...) at js/src/jsgc.cpp:5831
#13 0x00000000007a15b0 in js::gc::GCRuntime::gcCycle (this=this@entry=0x7ffff695f448, nonincrementalByAPI=nonincrementalByAPI@entry=false, budget=..., reason=reason@entry=JS::gcreason::DEBUG_GC) at js/src/jsgc.cpp:6109
#14 0x00000000007a1a1e in js::gc::GCRuntime::collect (this=this@entry=0x7ffff695f448, nonincrementalByAPI=nonincrementalByAPI@entry=false, budget=..., reason=reason@entry=JS::gcreason::DEBUG_GC) at js/src/jsgc.cpp:6212
#15 0x00000000007a228c in js::gc::GCRuntime::runDebugGC (this=this@entry=0x7ffff695f448) at js/src/jsgc.cpp:6717
#16 0x0000000000a62120 in js::gc::GCRuntime::gcIfNeededPerAllocation (this=0x7ffff695f448, cx=0x7ffff695f000) at js/src/gc/Allocator.cpp:224
#17 0x0000000000a6d5fd in js::gc::GCRuntime::checkAllocatorState<(js::AllowGC)1> (kind=js::gc::AllocKind::LAZY_SCRIPT, cx=<optimized out>, this=0x7ffff695f448) at js/src/gc/Allocator.cpp:189
#18 js::Allocate<js::LazyScript, (js::AllowGC)1> (cx=cx@entry=0x7ffff695f000) at js/src/gc/Allocator.cpp:139
#19 0x00000000007fee3a in js::LazyScript::CreateRaw (cx=0x7ffff695f000, fun=..., packedFields=<optimized out>, begin=492, end=611, lineno=lineno@entry=17, column=29) at js/src/jsscript.cpp:4274
#20 0x00000000007fefcf in js::LazyScript::CreateRaw (cx=<optimized out>, fun=..., fun@entry=..., numFreeVariables=<optimized out>, numInnerFunctions=numInnerFunctions@entry=0, version=<optimized out>, begin=<optimized out>, end=<optimized out>, lineno=17, column=29) at js/src/jsscript.cpp:4305
#21 0x0000000000487063 in js::frontend::Parser<js::frontend::SyntaxParseHandler>::finishFunctionDefinition (this=this@entry=0x7fffffffb888, funbox=funbox@entry=0x7ffff698b370, body=<optimized out>, pn=js::frontend::SyntaxParseHandler::NodeGeneric) at js/src/frontend/Parser.cpp:2900
#22 0x000000000049f34f in js::frontend::Parser<js::frontend::SyntaxParseHandler>::finishFunctionDefinition (body=<optimized out>, funbox=0x7ffff698b370, pn=js::frontend::SyntaxParseHandler::NodeGeneric, this=0x7fffffffb888) at /srv/jenkins/jobs/mozilla-central-build-jsshell/workspace/arch/64/compiler/gcc/sanitizer/none/type/opt/dist/include/js/RootingAPI.h:693
#23 js::frontend::Parser<js::frontend::SyntaxParseHandler>::functionArgsAndBodyGeneric (this=this@entry=0x7fffffffb888, inHandling=inHandling@entry=js::frontend::InAllowed, yieldHandling=yieldHandling@entry=js::frontend::YieldIsName, pn=pn@entry=js::frontend::SyntaxParseHandler::NodeGeneric, fun=fun@entry=..., kind=kind@entry=js::frontend::Statement) at js/src/frontend/Parser.cpp:3246
#24 0x000000000048e27f in js::frontend::Parser<js::frontend::FullParseHandler>::functionArgsAndBody (this=this@entry=0x7fffffffbd78, inHandling=inHandling@entry=js::frontend::InAllowed, pn=0x7ffff698b338, fun=..., fun@entry=..., kind=kind@entry=js::frontend::Statement, generatorKind=generatorKind@entry=js::NotGenerator, inheritedDirectives=..., newDirectives=0x7fffffffaf50) at js/src/frontend/Parser.cpp:2981
#25 0x00000000004a8b73 in js::frontend::Parser<js::frontend::FullParseHandler>::functionDef (this=this@entry=0x7fffffffbd78, inHandling=inHandling@entry=js::frontend::InAllowed, yieldHandling=yieldHandling@entry=js::frontend::YieldIsName, funName=..., funName@entry=..., kind=kind@entry=js::frontend::Statement, generatorKind=<optimized out>, invoked=js::frontend::Parser<js::frontend::FullParseHandler>::PredictUninvoked, assignmentForAnnexBOut=0x7fffffffb0a8) at js/src/frontend/Parser.cpp:2846
#26 0x00000000004a8f76 in js::frontend::Parser<js::frontend::FullParseHandler>::functionStmt (this=this@entry=0x7fffffffbd78, yieldHandling=yieldHandling@entry=js::frontend::YieldIsName, defaultHandling=defaultHandling@entry=js::frontend::NameRequired) at js/src/frontend/Parser.cpp:3315
#27 0x00000000004b232c in js::frontend::Parser<js::frontend::FullParseHandler>::statement (this=this@entry=0x7fffffffbd78, yieldHandling=yieldHandling@entry=js::frontend::YieldIsName, canHaveDirectives=<optimized out>) at js/src/frontend/Parser.cpp:7567
#28 0x00000000004b27f8 in js::frontend::Parser<js::frontend::FullParseHandler>::statements (this=this@entry=0x7fffffffbd78, yieldHandling=yieldHandling@entry=js::frontend::YieldIsName) at js/src/frontend/Parser.cpp:3564
#29 0x000000000048cde5 in js::frontend::Parser<js::frontend::FullParseHandler>::evalBody (this=0x7fffffffbd78) at js/src/frontend/Parser.cpp:1095
#30 0x0000000000a4e305 in BytecodeCompiler::compileScript (this=this@entry=0x7fffffffb780, scopeChain=..., scopeChain@entry=..., evalCaller=..., evalCaller@entry=...) at js/src/frontend/BytecodeCompiler.cpp:529
#31 0x0000000000a4e5f6 in js::frontend::CompileScript (cx=cx@entry=0x7ffff695f000, alloc=alloc@entry=0x7ffff695f360, scopeChain=scopeChain@entry=..., enclosingStaticScope=..., enclosingStaticScope@entry=..., evalCaller=evalCaller@entry=..., options=..., srcBuf=..., source_=0x7ffff20a01c0, extraSct=0x0, sourceObjectOut=0x0) at js/src/frontend/BytecodeCompiler.cpp:742
#32 0x000000000082c87b in EvalKernel (cx=cx@entry=0x7ffff695f000, v=..., v@entry=..., evalType=evalType@entry=DIRECT_EVAL, caller=..., scopeobj=scopeobj@entry=..., pc=0x7ffff693a187 "{", vp=...) at js/src/builtin/Eval.cpp:327
#33 0x000000000082cc7b in js::DirectEval (cx=cx@entry=0x7ffff695f000, v=..., vp=vp@entry=...) at js/src/builtin/Eval.cpp:457
#34 0x0000000000b819ac in js::jit::DoCallFallback (cx=0x7ffff695f000, frame=0x7fffffffd128, stub_=0x7ffff2759618, argc=1, vp=0x7fffffffd0d8, res=...) at js/src/jit/BaselineIC.cpp:5974
#35 0x00007ffff7e3ca5f in ?? ()
[...]
#71 0x0000000000000000 in ?? ()
rax 0x4b4b4b4b4b4b4b4b 5425512962855750475
rbx 0x7ffff366dac0 140737276992192
rcx 0x7ffff0eff160 140737235644768
rdx 0x4020000000000800 4620693217682130944
rsi 0x7ffff0ec3058 140737235398744
rdi 0x1 1
rbp 0xff8 4088
rsp 0x7fffffffa4d8 140737488331992
r8 0x7ffff36fdca0 140737277582496
r9 0x1000 4096
r10 0x0 0
r11 0x246 582
r12 0x7ffff6961550 140737330419024
r13 0x450 1104
r14 0x7ffff366d000 140737276989440
r15 0x7fffffffa840 140737488332864
rip 0xa79bd5 <js::GCMarker::markAndScan<JSString>(JSString*)+837>
=> 0xa79bd5 <js::GCMarker::markAndScan<JSString>(JSString*)+837>: mov (%rax),%edx
0xa79bd7 <js::GCMarker::markAndScan<JSString>(JSString*)+839>: and $0x28,%edx
The crash is intermittent (should crash within a minute and require maybe 10 runs) and reducing the test case further makes it almost impossible to reproduce. Marking s-s and sec-critical because the crash address indicates use-after-free. Might be a dup to one of the previous GC issues filed, but I can't really tell without a reduced test and we can't afford missing one of these.
Reporter | ||
Comment 1•8 years ago
|
||
(also fairly intermittent, crashing at js::GCMarker::eagerlyMarkChildren)
Run with --fuzzing-safe --thread-count=2 --ion-eager and tested with m-c rev bd7645928990.
CC="clang -Qunused-arguments" CXX="clang++ -Qunused-arguments" AR=ar AUTOCONF=/usr/local/Cellar/autoconf213/2.13/bin/autoconf213 sh /Users/skywalker/trees/mozilla-central/js/src/configure --target=x86_64-apple-darwin14.5.0 --disable-jemalloc --enable-debug --enable-more-deterministic --with-ccache --enable-gczeal --enable-debug-symbols --disable-tests
Managed to squeeze out a possible regression window:
autoBisect shows this is probably related to the following changeset:
The first bad revision is:
changeset: https://hg.mozilla.org/mozilla-central/rev/815c7d8dfebe
user: Michael Smith
date: Mon Jul 18 19:00:26 2016 -0700
summary: Bug 1282944 - Link excess lazy builders immediately, instead of throwing them away. (r=h4writer,efaust)
Michael, is bug 1282944 a likely regressor?
Flags: needinfo?(michael+bmo)
Digging into this now... It shouldn't be, but it's not impossible. Previously we threw away pending IonBuilders once our queue exceeded a certain threshold; that patch makes us excess builders immediately instead. But if the builders are in the pending link queue then linking them in should be safe...
Perhaps the removal of |AutoEnterAnalysis enterTypes(cx);| is related? AutoEnterAnalysis disables GC.
After completion, the IonBuilder and its LifoAlloc are deleted in FinishOffThreadBuilder: https://dxr.mozilla.org/mozilla-central/source/js/src/jit/Ion.cpp#505-510
It seems plausible that this could lead to a use-after-free through some confluence of circumstances.
Can I ping h4writer on this?
Alternatively, it could just be that linking in a particular IonBuilder / IonScript allows this test to reach a code path that it wouldn't otherwise, as the Ion code would have been thrown away and not used.
Flags: needinfo?(michael+bmo) → needinfo?(gary)
(In reply to Michael Smith [:mismith] from comment #6)
> Can I ping h4writer on this?
Sure, setting needinfo? for you. Also adding :jonco to cc list.
Flags: needinfo?(gary) → needinfo?(hv1989)
Looks like a regression from 50.
status-firefox49:
--- → unaffected
status-firefox50:
--- → affected
status-firefox-esr45:
--- → unaffected
Jan can you take a look?
Flags: needinfo?(jdemooij)
Comment 12•8 years ago
|
||
(In reply to Gary Kwong [:gkw] [:nth10sd] from comment #2)
> Created attachment 8784950 [details]
> another testcase
Thanks for the second testcase. That was reproducible for me. Cannot get the first one to work.
> Michael, is bug 1282944 a likely regressor?
I'm still investigating, but from what I see, I don't think it is introduced by that bug. There is some logs pointing to sharedStubs. Though from what I currently understand I think sharedStubs is not the reason. Investigating further to find the issue.
Comment 13•8 years ago
|
||
Maybe it's another bug that will be fixed by bug 1301343? You could try the patch there.
Comment 14•8 years ago
|
||
(In reply to Jan de Mooij [:jandem] from comment #13)
> Maybe it's another bug that will be fixed by bug 1301343? You could try the
> patch there.
That sounds very much like what I was experiencing. I looked a bit deeper to confirm that patch fix it.
(It is intermittent and quite fragile. Therefore I couldn't confirm by applying the patch)
I'm seeing the following:
The suspects are an ObjectGroup (lets call it group1) and a Atom/String (lets call it string1)
1) group1 is alive and well
2) We start IonBuilder compiling, which freezes a HeapTypeSetKey (with string1 as jsid)
3) ObjectGroup is getting marked
4) We free everything that isn't marked. We free jsid!
5) We link, where the freeze causes us to add the property to the Objectgroup
6) We start marking, which sees the jsid (which is already freed)
Flags: needinfo?(hv1989)
Updated•8 years ago
|
Status: NEW → RESOLVED
Closed: 8 years ago
Resolution: --- → DUPLICATE
Updated•8 years ago
|
status-firefox50:
affected → ---
status-firefox51:
affected → ---
Updated•6 years ago
|
Group: javascript-core-security
You need to log in
before you can comment on or make changes to this bug.
Description
•