Closed Bug 1346862 Opened 9 years ago Closed 9 years ago

Crash [@ js::UnwindEnvironment] or Assertion failure: !done(), at vm/Scope.h:1363

Categories

(Core :: JavaScript Engine, defect)

x86_64
Linux
defect
Not set
critical

Tracking

()

RESOLVED FIXED
mozilla55
Tracking Status
firefox52 --- unaffected
firefox-esr52 --- unaffected
firefox53 --- fixed
firefox54 --- fixed
firefox55 --- fixed

People

(Reporter: decoder, Assigned: shu)

References

Details

(5 keywords, Whiteboard: [jsbugmon:update])

Crash Data

Attachments

(4 files, 1 obsolete file)

The following testcase crashes on mozilla-central revision f9362554866b (build with --enable-posix-nspr-emulation --enable-valgrind --enable-gczeal --disable-tests --enable-stdcxx-compat --disable-profiling --disable-debug --enable-optimize, run with --baseline-eager): loadFile(` iterable = {} iterable[Symbol.iterator] = function() { return { next() { return {} }, return() { yield; } } } for (x of iterable) { try { return; } catch (get) {} let f; } `); function loadFile(lfVarx) { Function(lfVarx)(); } Backtrace: received signal SIGSEGV, Segmentation fault. js::UnwindEnvironment (cx=cx@entry=0x7ffff6926800, ei=..., pc=<optimized out>) at js/src/vm/Interpreter.cpp:1047 #0 js::UnwindEnvironment (cx=cx@entry=0x7ffff6926800, ei=..., pc=<optimized out>) at js/src/vm/Interpreter.cpp:1047 #1 0x00000000006513ee in js::jit::SettleOnTryNote (cx=cx@entry=0x7ffff6926800, tn=tn@entry=0x7ffff69ea9e8, frame=..., ei=..., rfe=rfe@entry=0x7fffffffc268, pc=pc@entry=0x7fffffffbc78) at js/src/jit/JitFrames.cpp:522 #2 0x0000000000655409 in js::jit::ProcessTryNotesBaseline (pc=0x7fffffffbc78, rfe=0x7fffffffc268, ei=..., frame=..., cx=0x7ffff6926800) at js/src/jit/JitFrames.cpp:604 #3 js::jit::HandleExceptionBaseline (pc=0x7ffff438c941 ":", rfe=0x7fffffffc268, frame=..., cx=0x7ffff6926800) at js/src/jit/JitFrames.cpp:724 #4 js::jit::HandleException (rfe=<optimized out>) at js/src/jit/JitFrames.cpp:890 #5 0x0000356b9406d15b in ?? () [...] #22 0x0000000000000000 in ?? () rax 0x0 0 rbx 0x7fffffffbdc0 140737488338368 rcx 0x1ac1460 28054624 rdx 0x0 0 rsi 0x1ac1500 28054784 rdi 0x7fffffffbdc0 140737488338368 rbp 0x7ffff6926800 140737330178048 rsp 0x7fffffffbb20 140737488337696 r8 0x7ffff69eaa28 140737330981416 r9 0x7ffff69ea9b0 140737330981296 r10 0x7ffff69ea980 140737330981248 r11 0x0 0 r12 0xdfb5dc 14661084 r13 0x7fffffffffff 140737488355327 r14 0x7fffffffbdd8 140737488338392 r15 0x7fffffffbb20 140737488337696 rip 0x4cb105 <js::UnwindEnvironment(JSContext*, js::EnvironmentIter&, unsigned char*)+197> => 0x4cb105 <js::UnwindEnvironment(JSContext*, js::EnvironmentIter&, unsigned char*)+197>: cmpb $0xe,(%rdx) 0x4cb108 <js::UnwindEnvironment(JSContext*, js::EnvironmentIter&, unsigned char*)+200>: ja 0x4cb141 <js::UnwindEnvironment(JSContext*, js::EnvironmentIter&, unsigned char*)+257>
Whiteboard: [jsbugmon:update,bisect] → [jsbugmon:update]
JSBugMon: Bisection requested, result: === Treeherder Build Bisection Results by autoBisect === The "good" changeset has the timestamp "20170113151323" and the hash "0431a0ab907d53646d359ad10507efe7f89dd487". The "bad" changeset has the timestamp "20170114194423" and the hash "18ab7878c67ba22b2f98bcc7a1e94b826061dd19". Likely regression window: https://hg.mozilla.org/integration/mozilla-inbound/pushloghtml?fromchange=0431a0ab907d53646d359ad10507efe7f89dd487&tochange=18ab7878c67ba22b2f98bcc7a1e94b826061dd19
Slightly more reduced testcase: (function () { z = {} z[Symbol.iterator] = function () { return { next() { return {} }, return () { yield; } } } for (x of z) { try { return; } catch (e) {} let f; } })()
Using the testcase in comment 2, with --fuzzing-safe --no-threads --no-baseline --no-ion: Due to skipped revisions, the first bad revision could be any of: changeset: https://hg.mozilla.org/mozilla-central/rev/757b50c0ee48 user: Shu-yu Guo date: Sat Jan 14 14:51:38 2017 -0800 summary: Bug 1147371 - Implement IteratorClose for for-of. (r=arai) changeset: https://hg.mozilla.org/mozilla-central/rev/8ad6c93e5162 user: Shu-yu Guo date: Sat Jan 14 14:51:38 2017 -0800 summary: Bug 1147371 - Rename allowContentSpread to allowContentIter. (r=arai) changeset: https://hg.mozilla.org/mozilla-central/rev/d7d332a5b2e8 user: Shu-yu Guo date: Sat Jan 14 14:51:38 2017 -0800 summary: Bug 1147371 - Convert self-hosted code that need to call IteratorClose to use for-of. (r=arai) changeset: https://hg.mozilla.org/mozilla-central/rev/ce293b3c0a8b user: Shu-yu Guo date: Sat Jan 14 14:51:38 2017 -0800 summary: Bug 1147371 - Implement IteratorClose for array destructuring. (r=arai) changeset: https://hg.mozilla.org/mozilla-central/rev/e0dc4150f8ac user: Shu-yu Guo date: Sat Jan 14 14:51:39 2017 -0800 summary: Bug 1147371 - Implement calling IteratorClose and "return" on iterators in yield*. (r=jandem) Shu-yu, is bug 1147371 a likely regressor?
Blocks: 1147371
Flags: needinfo?(shu)
Also includes a light refactoring of flushPops.
Attachment #8847394 - Flags: review?(arai.unmht)
Flags: needinfo?(shu)
looks good for this specific situation, but I don't yet understand how this change interacts with implicit try-catch for IteratorClose, and try-catch/try-finally outside of the innermost for-of, especially when the local jump is break/continue. I won't be able to do thorough review today and tomorrow, if this is urgent, feel free to redirect. if not, I'll review it this Friday or weekend.
maybe we should try moving IterarotClose code outside of the loop body, and jump there from non-local jump source? (of course in another bug tho)
(In reply to Tooru Fujisawa [:arai] (almost away until April) from comment #5) > looks good for this specific situation, but I don't yet understand how this > change interacts with implicit try-catch for IteratorClose, and > try-catch/try-finally outside of the innermost for-of, especially when the > local jump is break/continue. > The implicit try-catch around IteratorClose should still apply, since the IteratorClose's JSTRY_CATCH would match (and then terminate the try-note iteration in HandleError) before JSTRY_FOR_OF_ITERCLOSE. The THROW op should also be outside of the range of JSTRY_FOR_OF_ITERCLOSE. |continue| wouldn't call IteratorClose, so that's fine. As for try-catch and try-finally outside of the innermost for-of, are you thinking of something like the following? for (x of iter) { try { try { break; } catch (e1) {} } catch (e2) {} } In that case, inside HandleError, it'll look like we threw from IteratorClose inside |break|, setting |inForOfIterClose = true|. That won't be reset to false until we the try-note iter finds the JSTRY_FOR_OF, meaning neither of the two catch blocks will match. > I won't be able to do thorough review today and tomorrow, > if this is urgent, feel free to redirect. > if not, I'll review it this Friday or weekend. Thanks for letting me know. Not urgent, I'll wait.
thanks :) what I'm thinking is: try { for (x of y) { break/return; } } catch/finally {} or 2 or more for-of loops and break/continue to label outer: for (x of y) { try { // syntactic, or implicit for for-of for (z of w) { break outer/continue outer/return; } } catch/finally { } }
(In reply to Tooru Fujisawa [:arai] (almost away until April) from comment #8) > thanks :) > > what I'm thinking is: > > try { > for (x of y) { > break/return; > } > } catch/finally {} 1. JSTRY_FOR_OF_ITERCLOSE will set inForOfIterClose = true 2. The try-note iterator will see JSTRY_FOR_OF when iterating and set inForOfIterClose = false 3. The try-note iterator will see JSTRY_CATCH, and since inForOfIterClose == false, it will jump to it. > > or 2 or more for-of loops and break/continue to label > > outer: for (x of y) { > try { // syntactic, or implicit for for-of > for (z of w) { > break outer/continue outer/return; > } > } catch/finally { > } > } The same thing as above, really. The try-note iterator should see things in the right order.
ah, makes sense :D thank you for the detailed answer
Comment on attachment 8847394 [details] [diff] [review] Fix IteratorClose due to non-local jumps being catchable by try statements inside for-of. Review of attachment 8847394 [details] [diff] [review]: ----------------------------------------------------------------- ::: js/src/jit/JitFrames.cpp @@ +616,5 @@ > continue; > > + // See corresponding comment in ProcessTryNotes. > + if (inForOfIterClose) > + continue; Can we align either to "break" or "continue" between ProcessTryNotesBaseline and HandleExceptionIon ? (looks like both have same effect here and there) ::: js/src/tests/ecma_6/Statements/for-of-iterator-close-throw.js @@ +15,5 @@ > + assertThrowsValue(function() { > + for (var x of iterable) { > + try { > + return; > + } catch (e) { how about doing "catchEntered++" here and assert it's not executed? ::: js/src/vm/Interpreter.cpp @@ +1184,5 @@ > + // 2. Try-catch notes cannot be disjoint. That is, we can't have > + // multiple notes with disjoint pc ranges jumping to the same > + // catch block. > + if (inForOfIterClose) > + break; here too, this uses "break" but ProcessTryNotesBaseline uses "continue". it would be nice to use same statement everywhere. @@ +1191,5 @@ > > case JSTRY_FINALLY: > + // See note above. > + if (inForOfIterClose) > + break; and here.
Attachment #8847394 - Flags: review?(arai.unmht) → review+
Pushed by shu@rfrn.org: https://hg.mozilla.org/integration/mozilla-inbound/rev/6332c1ac93be Fix IteratorClose due to non-local jumps being catchable by try statements inside for-of. (r=arai)
Status: NEW → RESOLVED
Closed: 9 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla55
Please request Aurora/Beta approval on this when you get a chance.
Assignee: nobody → shu
Flags: needinfo?(shu)
Comment on attachment 8852102 [details] [diff] [review] Fix IteratorClose due to non-local jumps being catchable by try statements inside for-of. Approval Request Comment [Feature/Bug causing the regression]: bug 1147371 [User impact if declined]: incorrect behavior and crashes when JS code using the Iterator protocol throws from inside of IteratorClose [Is this code covered by automated tests?]: yes [Has the fix been verified in Nightly?]: yes [Needs manual test from QE? If yes, steps to reproduce]: no [List of other uplifts needed for the feature/fix]: none [Is the change risky?]: not risky [Why is the change risky/not risky?]: bug fix to a yet still rarely used corner of JS [String changes made/needed]: none
Flags: needinfo?(shu)
Attachment #8852102 - Flags: approval-mozilla-beta?
Attachment #8852102 - Flags: approval-mozilla-aurora?
Comment on attachment 8852102 [details] [diff] [review] Fix IteratorClose due to non-local jumps being catchable by try statements inside for-of. Fix a crash. Aurora54+ & Beta53+.
Attachment #8852102 - Flags: approval-mozilla-beta?
Attachment #8852102 - Flags: approval-mozilla-beta+
Attachment #8852102 - Flags: approval-mozilla-aurora?
Attachment #8852102 - Flags: approval-mozilla-aurora+
Looks like this'll need a rebased patch for Beta too.
Flags: needinfo?(shu)
What flags should I set on the rebased patches to get them landed?
Flags: needinfo?(shu)
Oops, mis-rebased an error handling thing that changed in the shell. The failing tests pass locally.
Attachment #8854157 - Attachment is obsolete: true
Flags: needinfo?(shu)
Setting qe-verify- based on Shu-yu Guo's assessment on manual testing needs (see Comment 16) and the fact that this fix has automated coverage.
Flags: qe-verify-
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: