Closed Bug 781859 Opened 12 years ago Closed 12 years ago

Assertion failure: lifetime && lifetime->head == uint32_t(head - outerScript->code) && lifetime->entry == uint32_t(entryTarget - outerScript->code), at methodjit/LoopState.cpp:80

Categories

(Core :: JavaScript Engine, defect)

x86_64
Linux
defect
Not set
critical

Tracking

()

VERIFIED FIXED
mozilla19
Tracking Status
firefox15 --- wontfix
firefox16 --- wontfix
firefox17 + fixed
firefox18 + fixed
firefox19 + fixed
firefox-esr10 --- unaffected

People

(Reporter: decoder, Assigned: bhackett1024)

References

Details

(4 keywords, Whiteboard: [js:p1:fx18] [jsbugmon:update,ignore][adv-track-main17+])

Attachments

(2 files, 3 obsolete files)

The following test asserts on mozilla-central revision b5ae446888f5 (options -m -n -a):


function e() {
    try {} catch (e) {
    return (actual = "FAIL");
      a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
      a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
      a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
      a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
      a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
      a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
      a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
      a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
      a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
      a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
      a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
      a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
      a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
      a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
      a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
      a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
      a.x + a.x + a.x + a.x + a.x + a.x + a.x + a.x
    }
    while (t) continue;
}
e();


I believe this is something different than bug 741110 and bug 770089 since the test looks entirely different and doesn't depend on mjitChunkLimit. S-s due to previous bugs with that assertion being security-relevant.
Whiteboard: [jsbugmon:update] → [jsbugmon:update,bisect]
Whiteboard: [jsbugmon:update,bisect] → [jsbugmon:update]
JSBugMon: Bisection requested, result:
autoBisect shows this is probably related to the following changeset:

The first bad revision is:
changeset:   87695:f4e955f78de9
user:        Jeff Walden
date:        Fri Feb 03 18:53:29 2012 -0800
summary:     Bug 720316 - Use uint32_t indexes for JOF_ATOM opcodes.  r=jorendorff
Waldo or Jason, mind taking a look at this?
sure.
Assignee: general → jorendorff
Provisionally calling this sec-critical. Always welcome thoughts from those closer to the code.
Keywords: sec-critical
Full assertion is:
    JS_ASSERT(lifetime &&
              lifetime->head == uint32_t(head - outerScript->code) &&
              lifetime->entry == uint32_t(entryTarget - outerScript->code));

lifetime->entry                   is 1507 (points to JSOP_LOOPHEAD)
entryTarget - outerScript->code   is 1506 (points to JSOP_LOOPENTRY)
Assignee: jorendorff → bhackett1024
Bug 720316 is likely a bogus dependency, just as the original dependency in bug 770089 was, and this possibly goes back to chunked compilation notwithstanding the absence of mjitChunkLimit from the testcase.  (In effect every script has an implicit |mjitChunkLimit(#)| call in it, actually, for some value of # that I don't know offhand.  This just manages to crash with whatever that default limit is.)  Therefore this might well be a dup of one of the other two bugs, although there's no actual evidence beyond the common assertion -- and, come to see it, this having a try-catch-then-loop structure in common with the testcase for bug 741110.  If there's a dup relationship, and there may well not be one, I bet it's with that bug.
Assignee: bhackett1024 → jwalden+bmo
Whiteboard: [jsbugmon:update] → [jsbugmon:update][js:p1:fx18]
I'm sure critsmash is going to be interested in this bug (and the other bugs with similar-looking assertions) today, so...

Right before he left bhackett said something about thinking the assertion was wrong, but he didn't give any explanation at the time, and I haven't been able to verify that one way or the other yet.  So the short answer is that I don't know yet what's up here.  (And obviously that doesn't apply to the one similar-looking bug where an out-and-out crash was reported.)
Thanks Jeff, it helps (really). Hopefully work on the other two bugs helps illuminate this one.
billm and I looked at this for half an hour or so on Thursday afternoon.  Neither of us understands chunked compilation, so we're pretty much stumbling in the dark on this.  And I have been told chunked compilation -- as done in JM, at least -- doesn't really have things like invariants.  So there's apparently not really a good way to understand how chunked compilation works.

dvander says jandem is the person best positioned to understand JM chunked compilation -- maybe he'd be able to figure this out quickly?  'cause it's going to take me awhile to do this, if I'm to be the one to do it.  :-\
Yeah this is a chunked compilation issue. While-loops have the following bytecode structure:

00000:  goto 6 (+6)
00005:  loophead
--- body ---
00006:  loopentry
--- condition ---
00008:  ifne 5 (-3)
00013:  stop

When splitting the script in chunks, we try to ensure the initial GOTO is in the same chunk as the LOOPHEAD following it. The way this works is if we are at op X, we check if X + 2 is a LOOPHEAD and if so start a new chunk at X + 1 (the GOTO).

This works fine in most cases, except if the op at offset X, before the GOTO, is unreachable/dead. Unreachable ops are skipped so we don't run the check and hence it's possible to start a chunk at the LOOPHEAD, and the GOTO is in a different chunk.

I tried to fix this in MakeJITScript, but it's not easy. A much simpler fix I think is to emit a JSOP_NOP right before the JSOP_GOTO. This is nice anyway because it matches what we emit for other loops.
Assignee: jwalden+bmo → jdemooij
Status: NEW → ASSIGNED
Attached patch Part 1: Add SRC_DO (obsolete) — Splinter Review
Once while loops also have a JSOP_NOP, we need a way to distinguish while and do-while loops when we see a JSOP_NOP with SRC_WHILE source note.

This patch adds a separate SRC_DO source note. It also slightly simplifies things since it can store two offsets, instead of using a second source note for the next op.
Attachment #667006 - Flags: review?(jorendorff)
Add JSOP_NOP before the initial JSOP_GOTO, and move the source note to it.
Attachment #667010 - Flags: review?(jorendorff)
Adds decompileFunctionDeprecated to the shell, I used this to test the decompiler changes in the other patches.
Attachment #667022 - Flags: review?(jorendorff)
Attached patch Patch v2Splinter Review
Jason asked some good questions, which made me realize it's actually simpler to allow a chunk boundary between the GOTO and LOOPHEAD, and fix the few places in the compiler where it assumes otherwise.
Attachment #667006 - Attachment is obsolete: true
Attachment #667010 - Attachment is obsolete: true
Attachment #667022 - Attachment is obsolete: true
Attachment #667006 - Flags: review?(jorendorff)
Attachment #667010 - Flags: review?(jorendorff)
Attachment #667022 - Flags: review?(jorendorff)
Attachment #667095 - Flags: review?(dvander)
Attachment #667095 - Flags: review?(dvander) → review+
jandem, do you mind adding the testcase from bug 797163 as well, when you fix up and reland the patch?
(In reply to Gary Kwong [:gkw, :nth10sd] from comment #20)
> jandem, do you mind adding the testcase from bug 797163 as well, when you
> fix up and reland the patch?

Sure I will add it, thanks for the tests!
Blocks: 797163
Comment on attachment 667095 [details] [diff] [review]
Patch v2

gkw or decoder, could one of you fuzz this patch for a while with --no-ion? Reducing the M8 correctness bug will take a lot of time, so it would be very useful if the fuzzers could find a shell testcase in a few minutes. Thanks!
Attachment #667095 - Flags: feedback?(gary)
Attachment #667095 - Flags: feedback?(choller)
> gkw or decoder, could one of you fuzz this patch for a while with --no-ion?

Don't hold your hopes too high from me, I've fuzzed for an hour or two but nothing has showed up yet.
Comment on attachment 667095 [details] [diff] [review]
Patch v2

I didn't see anything here after a day of fuzzing with the patch.
Attachment #667095 - Flags: feedback?(gary) → feedback+
Attached patch patchSplinter Review
This patch seems to work ok, it doesn't skip unreachable opcodes while constructing chunks but just treats them as non-branching.  Passes jit-tests -mna and the three testcases in the comment 17 patch (will include those testcases when pushing).  I'm not sure what's wrong with the comment 17 patch but the code handling loop heads wrt OSR, LICM and loop-carried registers is pretty delicate (why the chunked compilation patch originally opted to not insert chunk boundaries in weird places).
Assignee: jdemooij → bhackett1024
Attachment #674069 - Flags: review?(jdemooij)
Comment on attachment 674069 [details] [diff] [review]
patch

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

Nice minimal fix, thanks.
Attachment #674069 - Flags: review?(jdemooij) → review+
Attachment #667095 - Flags: feedback?(choller)
This is a sec-high bug. It should have been nominated with the sec-approval flag on the patch and received explicit approval for landing. This is now the policy for all sec-high and sec-critical issues. See posts to dev.planning on this and https://wiki.mozilla.org/Security/Bug_Approval_Process.
(In reply to Brian Hackett (:bhackett) [mostly gone until mid-November] from comment #28)
> https://hg.mozilla.org/integration/mozilla-inbound/rev/0d60a2c574f4

If this is low risk enough for uplift to FF17, please nominate for uplift asap.
Whiteboard: [jsbugmon:update][js:p1:fx18] → [js:p1:fx18] [jsbugmon:update,ignore]
JSBugMon: The testcase found in this bug no longer reproduces (tried revision 93cc1ee94291).
https://hg.mozilla.org/mozilla-central/rev/0d60a2c574f4
Status: ASSIGNED → RESOLVED
Closed: 12 years ago
Flags: in-testsuite+
Resolution: --- → FIXED
Target Milestone: --- → mozilla19
Status: RESOLVED → VERIFIED
JSBugMon: This bug has been automatically verified fixed.
Comment on attachment 674069 [details] [diff] [review]
patch

[Approval Request Comment]
Bug caused by (feature/regressing bug #): chunked compilation (old)
User impact if declined: potential security bug
Testing completed (on m-c, etc.): yes
Risk to taking this patch (and alternatives if risky): This patch only changes how we ignore unreachable JavaScript code. Low-risk.
String or UUID changes made by this patch:
Attachment #674069 - Flags: approval-mozilla-beta?
Attachment #674069 - Flags: approval-mozilla-aurora?
Attachment #674069 - Flags: approval-mozilla-beta?
Attachment #674069 - Flags: approval-mozilla-beta+
Attachment #674069 - Flags: approval-mozilla-aurora?
Attachment #674069 - Flags: approval-mozilla-aurora+
Needs landing for aurora/beta.
Keywords: checkin-needed
Whiteboard: [js:p1:fx18] [jsbugmon:update,ignore] → [js:p1:fx18] [jsbugmon:update,ignore][adv-track-main17+]
Is there somewhere I can look at test results so I can mark this verified for Firefox 17, 18, and 19?
+1 to Anthony.

QA would love to regress this bug on affected branches. A link to test results OR a working test case that we can run would suffice. Thank you.
Group: core-security
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: