Assertion failure: frame.isDebuggee(), at js/src/debugger/Debugger.cpp:3186
Categories
(Core :: JavaScript Engine, defect, P1)
Tracking
()
Tracking | Status | |
---|---|---|
firefox-esr60 | --- | unaffected |
firefox-esr68 | --- | unaffected |
firefox67 | --- | unaffected |
firefox68 | --- | unaffected |
firefox69 | --- | wontfix |
firefox70 | --- | wontfix |
firefox71 | --- | fixed |
People
(Reporter: decoder, Assigned: jimb)
References
(Regression)
Details
(4 keywords, Whiteboard: [jsbugmon:update][debugger-mvp])
Attachments
(1 file)
The following testcase crashes on mozilla-central revision b94a6b06c9b9 (build with --enable-valgrind --enable-gczeal --disable-tests --disable-profiling --enable-debug --enable-optimize, run with --fuzzing-safe --ion-offthread-compile=off):
g = newGlobal({ newCompartment: true });
g.parent = this
g.eval("(" + function() {
Debugger(parent).onExceptionUnwind = function(frame) {
frame.older
}
} + ")()")
function* countdown(n38) {
while (n38 > 0) {
yield* countdown(--n38);
}
return apply != 3;
}
function collect_results(iter) {
result = iter.next();
}
collect_results(countdown(3));
Backtrace:
received signal SIGSEGV, Segmentation fault.
#0 js::Debugger::ensureExecutionObservabilityOfFrame (cx=0x7ffff5f23000, frame=...) at js/src/debugger/Debugger.cpp:3185
#1 0x0000555555e2b84a in js::Debugger::getFrame (this=this@entry=0x7ffff5f71000, cx=<optimized out>, cx@entry=0x7ffff5f23000, iter=..., result=..., result@entry=...) at js/src/debugger/Debugger.cpp:592
#2 0x0000555555e2bdf5 in js::DebuggerFrame::getOlder (cx=0x7ffff5f23000, frame=..., frame@entry=..., result=..., result@entry=...) at js/src/debugger/Frame.cpp:516
#3 0x0000555555e2bf5a in js::DebuggerFrame::olderGetter (cx=<optimized out>, cx@entry=0x7ffff5f23000, argc=<optimized out>, vp=<optimized out>) at js/src/debugger/Frame.cpp:1217
#4 0x00005555558e789f in CallJSNative (cx=0x7ffff5f23000, native=native@entry=0x555555e2beb0 <js::DebuggerFrame::olderGetter(JSContext*, unsigned int, JS::Value*)>, args=...) at js/src/vm/Interpreter.cpp:448
#5 0x00005555558de00a in js::InternalCallOrConstruct (cx=<optimized out>, cx@entry=0x7ffff5f23000, args=..., construct=construct@entry=js::NO_CONSTRUCT) at js/src/vm/Interpreter.cpp:540
#6 0x00005555558de76f in InternalCall (cx=cx@entry=0x7ffff5f23000, args=...) at js/src/vm/Interpreter.cpp:595
#7 0x00005555558de8f0 in js::Call (cx=cx@entry=0x7ffff5f23000, fval=..., fval@entry=..., thisv=..., thisv@entry=..., args=..., rval=...) at js/src/vm/Interpreter.cpp:611
#8 0x00005555558deaa8 in js::CallGetter (cx=0x7ffff5f23000, thisv=..., thisv@entry=..., getter=..., getter@entry=..., rval=..., rval@entry=...) at js/src/vm/Interpreter.cpp:735
#9 0x0000555555b17120 in CallGetter (vp=..., shape=..., receiver=..., obj=..., cx=<optimized out>) at js/src/vm/NativeObject.cpp:2269
#10 GetExistingProperty<(js::AllowGC)1> (cx=0x7ffff5f23000, receiver=..., obj=..., shape=..., vp=...) at js/src/vm/NativeObject.cpp:2324
#11 0x0000555555b19d04 in NativeGetPropertyInline<(js::AllowGC)1> (cx=<optimized out>, cx@entry=0x7ffff5f23000, obj=..., receiver=..., id=..., nameLookup=nameLookup@entry=NotNameLookup, vp=...) at js/src/vm/NativeObject.cpp:2570
#12 0x0000555555b1a310 in js::NativeGetProperty (cx=cx@entry=0x7ffff5f23000, obj=..., receiver=..., receiver@entry=..., id=..., id@entry=..., vp=..., vp@entry=...) at js/src/vm/NativeObject.cpp:2608
#13 0x00005555558eb3a4 in js::GetProperty (cx=0x7ffff5f23000, obj=..., receiver=..., id=..., vp=...) at js/src/vm/ObjectOperations-inl.h:117
#14 0x00005555558c9920 in js::GetProperty (vp=..., name=<optimized out>, receiver=..., obj=..., cx=<optimized out>) at js/src/vm/ObjectOperations-inl.h:124
#15 js::GetProperty (cx=<optimized out>, v=..., name=..., vp=...) at js/src/vm/Interpreter.cpp:4513
#16 0x00005555558cfabb in GetPropertyOperation (vp=..., lval=..., pc=<optimized out>, script=..., fp=<optimized out>, cx=0x7ffff5f23000) at js/src/vm/Interpreter.cpp:218
#17 Interpret (cx=0x7ffff5f23000, state=...) at js/src/vm/Interpreter.cpp:2771
#18 0x00005555558dd9f6 in js::RunScript (cx=0x7ffff5f23000, state=...) at js/src/vm/Interpreter.cpp:425
#19 0x00005555558de32f in js::InternalCallOrConstruct (cx=<optimized out>, cx@entry=0x7ffff5f23000, args=..., construct=construct@entry=js::NO_CONSTRUCT) at js/src/vm/Interpreter.cpp:568
#20 0x00005555558de76f in InternalCall (cx=0x7ffff5f23000, args=...) at js/src/vm/Interpreter.cpp:595
#21 0x00005555558de8f0 in js::Call (cx=<optimized out>, fval=..., fval@entry=..., thisv=..., thisv@entry=..., args=..., rval=...) at js/src/vm/Interpreter.cpp:611
#22 0x0000555555e366bc in js::Call (rval=..., arg1=..., arg0=..., thisObj=<optimized out>, fval=..., cx=<optimized out>) at js/src/vm/Interpreter.h:123
#23 js::Debugger::fireExceptionUnwind (this=this@entry=0x7ffff5f71000, cx=<optimized out>, vp=..., vp@entry=...) at js/src/debugger/Debugger.cpp:2086
#24 0x0000555555e3c335 in js::DebugAPI::<lambda(js::Debugger*)>::operator() (dbg=0x7ffff5f71000, __closure=<synthetic pointer>) at js/src/debugger/Debugger.cpp:1073
#25 js::Debugger::dispatchHook<js::DebugAPI::slowPathOnExceptionUnwind...) at js/src/debugger/Debugger.cpp:2214
#26 js::DebugAPI::slowPathOnExceptionUnwind (cx=<optimized out>, frame=...) at js/src/debugger/Debugger.cpp:1074
#27 0x00005555558cf1e8 in js::DebugAPI::onExceptionUnwind (frame=..., frame@entry=..., cx=<optimized out>) at js/src/debugger/DebugAPI-inl.h:151
#28 HandleError (regs=..., cx=<optimized out>) at js/src/vm/Interpreter.cpp:1245
#29 Interpret (cx=0x7ffff5f23000, state=...) at js/src/vm/Interpreter.cpp:4392
[...]
#39 main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at js/src/shell/js.cpp:11375
rax 0x555557cfb200 93825033810432
rbx 0x7fffffffab08 140737488333576
rcx 0x555556c3fae0 93825016265440
rdx 0x0 0
rsi 0x7ffff6eeb770 140737336227696
rdi 0x7ffff6eea540 140737336223040
rbp 0x7fffffffab60 140737488333664
rsp 0x7fffffffab00 140737488333568
r8 0x7ffff6eeb770 140737336227696
r9 0x7ffff7fe6cc0 140737354034368
r10 0x58 88
r11 0x7ffff6b927a0 140737332717472
r12 0x7ffff5f23000 140737319677952
r13 0x7ffff5f71158 140737319997784
r14 0x7fffffffac60 140737488333920
r15 0x7fffffffad40 140737488334144
rip 0x555555e066e9 <js::Debugger::ensureExecutionObservabilityOfFrame(JSContext*, js::AbstractFramePtr)+297>
=> 0x555555e066e9 <js::Debugger::ensureExecutionObservabilityOfFrame(JSContext*, js::AbstractFramePtr)+297>: movl $0x0,0x0
0x555555e066f4 <js::Debugger::ensureExecutionObservabilityOfFrame(JSContext*, js::AbstractFramePtr)+308>: ud2
Updated•5 years ago
|
autobisectjs shows this is probably related to the following changeset:
The first bad revision is:
changeset: https://hg.mozilla.org/mozilla-central/rev/8a7c8f8ecd56
user: Jim Blandy
date: Mon Jun 10 20:06:34 2019 +0000
summary: Bug 1539654: Ensure generator scripts observed by Debugger.Frames are marked as debuggees. r=jorendorff
Jim, is bug 1539654 a likely regressor?
Comment 2•5 years ago
|
||
Emailing followup.
Updated•5 years ago
|
Assignee | ||
Comment 4•5 years ago
|
||
The bug is that js::DebuggerFrame::setGenerator
increments the frame's script's generator observer count, making the script a debuggee, without marking all frames running that script debuggees as well. This violates the invariant that any frame running a debuggee script must itself be a debuggee.
The ensureExecutionObservability...
functions are designed to cope with this sort of thing; I think setGenerator
may need to be using one of those, rather than calling DebugScript::incrementGeneratorObserverCount
directly.
Updated•5 years ago
|
Assignee | ||
Updated•5 years ago
|
Updated•5 years ago
|
Assignee | ||
Comment 5•5 years ago
|
||
A Debugger.Frame referring to a generator or async call must track all
resumptions of that call. For the debugger to detect resumptions, the
generator/async function's script must be compiled with instrumentation on
JSOP_AFTERYIELD bytecodes. DebuggerFrame::setGenerator calls DebugScript::
incrementGeneratorObserverCount to request this.
However, incrementing the generator observer count marks the script as a
debuggee script. It is an invariant of the debugger that all frames running
debuggee scripts must themselves be marked as debuggee frames. So
DebuggerFrame::setGenerator needs to also call
Debugger::ensureExecutionObservabilityOfScript, which walks the stack and marks
other frames as debuggees where necessary.
Assignee | ||
Comment 6•5 years ago
|
||
Assignee | ||
Comment 8•5 years ago
|
||
Waiting on review from jorendorff. I'll ping him.
Comment 9•5 years ago
|
||
Jason if you can review this patch it can at least make it into 71 nightly (if not 70)
Assignee | ||
Updated•5 years ago
|
Assignee | ||
Comment 10•5 years ago
|
||
Reviewer changed to Ted Campbell.
Comment 11•5 years ago
|
||
Comment 12•5 years ago
|
||
bugherder |
Updated•5 years ago
|
Updated•3 years ago
|
Description
•