Closed Bug 1215678 Opened 5 years ago Closed 5 years ago

Crash [@ GetObjectClass] with OOM

Categories

(Core :: JavaScript Engine, defect, critical)

x86_64
Linux
defect
Not set
critical

Tracking

()

RESOLVED FIXED
mozilla44
Tracking Status
firefox43 --- unaffected
firefox44 --- fixed
firefox-esr38 --- unaffected

People

(Reporter: decoder, Assigned: jonco)

References

(Blocks 1 open bug)

Details

(5 keywords, Whiteboard: [jsbugmon:origRev=f7b746b4e913])

Crash Data

Attachments

(1 file)

The following testcase crashes on mozilla-central revision d374d16cbb25 (build with --enable-optimize --enable-posix-nspr-emulation --enable-valgrind --enable-gczeal --disable-tests --enable-debug, run with --fuzzing-safe --thread-count=2 --ion-check-range-analysis --ion-extra-checks --ion-offthread-compile=off):

enableShellObjectMetadataCallback()
oomTest(() => {
  newGlobal()
})
gczeal(9, 1);
a; 



Backtrace:

Program received signal SIGSEGV, Segmentation fault.
0x000000000095842b in GetObjectClass (obj=0x7fffee32f060) at js/src/jsfriendapi.h:626
#0  0x000000000095842b in GetObjectClass (obj=0x7fffee32f060) at js/src/jsfriendapi.h:626
#1  IsProxy (obj=0x7fffee32f060) at ../../dist/include/js/Proxy.h:434
#2  IsWrapper (obj=0x7fffee32f060) at js/src/jswrapper.h:275
#3  is<js::WrapperObject> (this=0x7fffee32f060) at js/src/vm/WrapperObject.h:35
#4  js::UncheckedUnwrap (wrapped=0x7fffee32f060, stopAtOuter=<optimized out>, flagsp=0x0) at js/src/proxy/Wrapper.cpp:62
#5  0x0000000000946695 in getDelegate (this=0x7ffff29d9100, key=<optimized out>) at js/src/jsweakmap.h:279
#6  keyNeedsMark (this=0x7ffff29d9100, key=<optimized out>) at js/src/jsweakmap.h:287
#7  js::WeakMap<js::PreBarriered<JSObject*>, js::RelocatablePtr<JS::Value>, js::DefaultHasher<js::PreBarriered<JSObject*> > >::markEphemeronEntries (this=0x7ffff29d9100, trc=0x7ffff693e230) at js/src/jsweakmap.h:230
#8  0x0000000000b8369b in js::GCMarker::enterWeakMarkingMode (this=this@entry=0x7ffff693e230) at js/src/gc/Marking.cpp:1780
#9  0x00000000008dc69d in js::gc::GCRuntime::markWeakReferences<js::gc::GCZoneGroupIter> (this=this@entry=0x7ffff693c410, phase=phase@entry=js::gcstats::PHASE_SWEEP_MARK_WEAK) at js/src/jsgc.cpp:4066
#10 0x00000000008a61b0 in markWeakReferencesInCurrentGroup (phase=js::gcstats::PHASE_SWEEP_MARK_WEAK, this=0x7ffff693c410) at js/src/jsgc.cpp:4099
#11 js::gc::GCRuntime::endMarkingZoneGroup (this=this@entry=0x7ffff693c410) at js/src/jsgc.cpp:4828
#12 0x00000000008b9852 in js::gc::GCRuntime::sweepPhase (this=this@entry=0x7ffff693c410, sliceBudget=...) at js/src/jsgc.cpp:5414
#13 0x00000000008bdfa5 in js::gc::GCRuntime::incrementalCollectSlice (this=this@entry=0x7ffff693c410, budget=..., reason=reason@entry=JS::gcreason::DEBUG_GC) at js/src/jsgc.cpp:6010
#14 0x00000000008bedc3 in js::gc::GCRuntime::gcCycle (this=this@entry=0x7ffff693c410, nonincrementalByAPI=nonincrementalByAPI@entry=false, budget=..., reason=reason@entry=JS::gcreason::DEBUG_GC) at js/src/jsgc.cpp:6222
#15 0x00000000008bf3da in js::gc::GCRuntime::collect (this=this@entry=0x7ffff693c410, nonincrementalByAPI=nonincrementalByAPI@entry=false, budget=..., reason=reason@entry=JS::gcreason::DEBUG_GC) at js/src/jsgc.cpp:6338
#16 0x00000000008bffa4 in js::gc::GCRuntime::runDebugGC (this=this@entry=0x7ffff693c410) at js/src/jsgc.cpp:6872
#17 0x0000000000b81107 in js::gc::GCRuntime::gcIfNeededPerAllocation (this=this@entry=0x7ffff693c410, cx=cx@entry=0x7ffff6907400) at js/src/gc/Allocator.cpp:28
#18 0x0000000000b90f4f in js::gc::GCRuntime::checkAllocatorState<(js::AllowGC)1> (this=0x7ffff693c410, cx=0x7ffff6907400, kind=js::gc::FAT_INLINE_STRING) at js/src/gc/Allocator.cpp:55
#19 0x0000000000b93364 in js::Allocate<JSFatInlineString, (js::AllowGC)1> (cx=0x7ffff6907400) at js/src/gc/Allocator.cpp:211
#20 0x0000000000a9057e in new_<(js::AllowGC)1> (cx=<optimized out>) at js/src/vm/String-inl.h:257
#21 js::AllocateInlineString<(js::AllowGC)1, unsigned char> (cx=<optimized out>, len=16, chars=0x7fffffffc700) at js/src/vm/String-inl.h:37
#22 0x0000000000a9f9b7 in NewInlineStringDeflated<(js::AllowGC)1> (chars=..., cx=0x7ffff6907400) at js/src/vm/String.cpp:1011
#23 NewStringDeflated<(js::AllowGC)1> (cx=0x7ffff6907400, s=<optimized out>, n=<optimized out>) at js/src/vm/String.cpp:1028
#24 0x000000000083b6f6 in NewStringCopyZ<(js::AllowGC)1> (s=0x7ffff46d8bb0 u"a is not defined", cx=0x7ffff6907400) at js/src/vm/String.h:1180
#25 JS_NewUCStringCopyZ (cx=cx@entry=0x7ffff6907400, s=0x7ffff46d8bb0 u"a is not defined") at js/src/jsapi.cpp:5013
#26 0x000000000086df00 in js::ErrorToException (cx=cx@entry=0x7ffff6907400, message=message@entry=0x7fffee9d6b60 "a is not defined", reportp=reportp@entry=0x7fffffffc990, callback=<optimized out>, userRef=<optimized out>) at js/src/jsexn.cpp:560
#27 0x000000000086e26e in ReportError (cx=0x7ffff6907400, message=0x7fffee9d6b60 "a is not defined", reportp=0x7fffffffc990, callback=<optimized out>, userRef=<optimized out>) at js/src/jscntxt.cpp:230
#28 0x000000000087051a in js::ReportErrorNumberVA (cx=0x7ffff6907400, flags=flags@entry=0, callback=0x85c1b0 <js::GetErrorMessage(void*, unsigned int)>, userRef=0x0, errorNumber=1, argumentsType=argumentsType@entry=js::ArgumentsAreASCII, ap=ap@entry=0x7fffffffca58) at js/src/jscntxt.cpp:754
#29 0x000000000083cf5b in JS_ReportErrorNumberVA (cx=<optimized out>, errorCallback=<optimized out>, userRef=<optimized out>, errorNumber=<optimized out>, ap=ap@entry=0x7fffffffca58) at js/src/jsapi.cpp:5510
#30 0x000000000083cfe6 in JS_ReportErrorNumber (cx=cx@entry=0x7ffff6907400, errorCallback=errorCallback@entry=0x85c1b0 <js::GetErrorMessage(void*, unsigned int)>, userRef=userRef@entry=0x0, errorNumber=errorNumber@entry=1) at js/src/jsapi.cpp:5499
#31 0x0000000000863d86 in js::ReportIsNotDefined (cx=cx@entry=0x7ffff6907400, id=id@entry=...) at js/src/jscntxt.cpp:832
#32 0x0000000000863e04 in js::ReportIsNotDefined (cx=0x7ffff6907400, name=..., name@entry=...) at js/src/jscntxt.cpp:840
#33 0x0000000000693278 in js::FetchName<false> (cx=0x7ffff6907400, obj=..., obj2=..., name=..., shape=..., vp=...) at js/src/vm/Interpreter-inl.h:201
#34 0x00000000009d28ca in GetNameOperation (vp=..., pc=<optimized out>, fp=<optimized out>, cx=0x7ffff6907400) at js/src/vm/Interpreter.cpp:302
#35 Interpret (cx=cx@entry=0x7ffff6907400, state=...) at js/src/vm/Interpreter.cpp:3234
#36 0x00000000009dfbbb in js::RunScript (cx=cx@entry=0x7ffff6907400, state=...) at js/src/vm/Interpreter.cpp:725
#37 0x00000000009e25dc in js::ExecuteKernel (cx=cx@entry=0x7ffff6907400, script=..., script@entry=..., scopeChainArg=..., thisv=..., newTargetValue=..., type=<optimized out>, evalInFrame=..., evalInFrame@entry=..., result=result@entry=0x0) at js/src/vm/Interpreter.cpp:1000
#38 0x00000000009e2a49 in js::Execute (cx=cx@entry=0x7ffff6907400, script=script@entry=..., scopeChainArg=..., rval=rval@entry=0x0) at js/src/vm/Interpreter.cpp:1035
#39 0x000000000083a908 in ExecuteScript (cx=cx@entry=0x7ffff6907400, scope=scope@entry=..., script=script@entry=..., rval=rval@entry=0x0) at js/src/jsapi.cpp:4598
#40 0x000000000083aae3 in JS_ExecuteScript (cx=cx@entry=0x7ffff6907400, scriptArg=scriptArg@entry=...) at js/src/jsapi.cpp:4631
#41 0x000000000042885f in RunFile (compileOnly=false, file=0x7ffff46df800, filename=0x7fffffffdff0 "min.js", cx=0x7ffff6907400) at js/src/shell/js.cpp:509
#42 Process (cx=cx@entry=0x7ffff6907400, filename=0x7fffffffdff0 "min.js", forceTTY=forceTTY@entry=false) at js/src/shell/js.cpp:628
#43 0x000000000048464a in ProcessArgs (op=0x7fffffffda20, cx=0x7ffff6907400) at js/src/shell/js.cpp:5994
#44 Shell (envp=<optimized out>, op=0x7fffffffda20, cx=0x7ffff6907400) at js/src/shell/js.cpp:6297
#45 main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at js/src/shell/js.cpp:6654
rax	0xfffc4b4b4b4b4b4b	-1043113148986549
rbx	0x7fffee32f060	140737189703776
rcx	0x7fffee32f060	140737189703776
rdx	0x0	0
rsi	0xeedc38	15653944
rdi	0x7ffff7e612e0	140737352438496
rbp	0x7fffffffbe40	140737488338496
rsp	0x7fffffffbe10	140737488338448
r8	0x7fffee52d770	140737191794544
r9	0x7ffff6a01018	140737331073048
r10	0x7fffee52d718	140737191794456
r11	0x7fffee536f18	140737191833368
r12	0x0	0
r13	0x1	1
r14	0xfffb7fffffffffff	-1266637395197953
r15	0xbad0bad1	3134241489
rip	0x95842b <js::UncheckedUnwrap(JSObject*, bool, unsigned int*)+235>
=> 0x95842b <js::UncheckedUnwrap(JSObject*, bool, unsigned int*)+235>:	mov    (%rax),%rax
   0x95842e <js::UncheckedUnwrap(JSObject*, bool, unsigned int*)+238>:	testb  $0x10,0xa(%rax)

Marking s-s because the crash involves a dangerous crash pattern (0x4b4b4b4b).
Whiteboard: [jsbugmon:update,bisect] → [jsbugmon:update]
JSBugMon: Bisection requested, result:
=== Treeherder Build Bisection Results by autoBisect ===

The "good" changeset has the timestamp "20151013053056" and the hash "8d9c20c241be7d7b3cfa90a3368a77db42172781".
The "bad" changeset has the timestamp "20151013054956" and the hash "d80f9d6921f8209ef01aa730be9a97ab727704d1".

Likely regression window: https://hg.mozilla.org/integration/mozilla-inbound/pushloghtml?fromchange=8d9c20c241be7d7b3cfa90a3368a77db42172781&tochange=d80f9d6921f8209ef01aa730be9a97ab727704d1
Whiteboard: [jsbugmon:update] → [jsbugmon:update,ignore]
JSBugMon: The testcase found in this bug no longer reproduces (tried revision f7b746b4e913).
Is it worth finding a fixed range to be sure this is fixed or should we close this as "works for me"?
Flags: needinfo?(choller)
This still reproduces for me on m-c rev f7b746b4e913 with:

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-darwin12.5.0 --enable-debug --disable-threadsafe --enable-more-deterministic --with-ccache --enable-gczeal --enable-debug-symbols --disable-tests
Whiteboard: [jsbugmon:update,ignore] → [jsbugmon:update,origRev=f7b746b4e913]
Whiteboard: [jsbugmon:update,origRev=f7b746b4e913] → [jsbugmon:origRev=f7b746b4e913]
JSBugMon: Cannot process bug: Unable to automatically reproduce, please track manually.
clearing needinfo as it still reproduces for gkw according to comment 4.
Flags: needinfo?(choller)
What's happening here is that the object metadata callback is putting a pointer to a cross compartment wrapper into a weakmap, but we're hitting OOM before we add the wrapper to the CCW map.  This breaks our invariant that all wrappers are in the map, and means that we do not mark the wrapped object.  We do still mark the weakmap, and this causes us to try to get the target of the wrapper.  We end up doing this after the target has been swept and we crash.

So this is a use after free.  It does depend on the shell's object metadata callback, but I guess other implementations of this callback could easily do the same thing.  I guess that makes the issue debugger-only though.
Assignee: nobody → jcoppeard
Attachment #8679505 - Flags: review?(terrence)
Comment on attachment 8679505 [details] [diff] [review]
bug1215678-ccw-oom

Review of attachment 8679505 [details] [diff] [review]:
-----------------------------------------------------------------

::: js/src/jscompartment.cpp
@@ +472,3 @@
>          return false;
>  
> +    printf("Allocated wrapper %p\n", wrapper.get());

Did you forgot to qref?
Attachment #8679505 - Flags: review?(terrence) → review+
It sounds like this is a debugger-only issue that is going to be hard to trigger so I'm going to mark it sec-moderate.
https://hg.mozilla.org/mozilla-central/rev/5aa82c988f71
Status: NEW → RESOLVED
Closed: 5 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla44
Duplicate of this bug: 1218986
Group: javascript-core-security → core-security-release
Duplicate of this bug: 1216599
Decoder, can you get JSBugMon to try to verify this fix again? Thank you.
Flags: needinfo?(choller)
Marking 43 as unaffected based on change dates.
Group: core-security-release
JSBugMon wasn't able to track this, most likely due to the error being OOM.
Flags: needinfo?(choller)
You need to log in before you can comment on or make changes to this bug.