Last Comment Bug 515811 - "ASSERTION: Some PresArena objects were not freed" with -moz-column, floats, huge font
: "ASSERTION: Some PresArena objects were not freed" with -moz-column, floats, ...
Status: RESOLVED FIXED
: [sg:critical?] for 1.9.2 branch and e...
: assertion, crash, fixed1.9.0.16, testcase, verified1.9.1
Product: Core
Classification: Components
Component: Layout
: Trunk
: x86 Mac OS X
: -- normal (vote)
: mozilla1.9.2
Assigned To: Timothy Nikkel (:tn)
: layout
:
:
: 306939 framedest 522170
  Show dependency treegraph
 
Reported: 2009-09-10 16:21 PDT by Jesse Ruderman
Modified: 2010-04-06 17:15 PDT (History)
10 users (show)
roc: wanted1.9.2+
tnikkel: in‑testsuite+
See Also:
Crash Signature:
  ---
  ---
  ---
  ---
  ---
  ---
  ---
  ---
  ---
  ---
  ---
  ---
  beta2-fixed
  ---
  .6-fixed


Attachments
testcase (triggers assertion when closed) (278 bytes, text/html)
2009-09-10 16:21 PDT, Jesse Ruderman
no flags Details
patch (1.82 KB, patch)
2009-09-15 00:41 PDT, Timothy Nikkel (:tn)
fantasai.bugs: review+
dbaron: superreview+
shaver: approval1.9.2+
dveditz: approval1.9.1.6+
dveditz: approval1.9.0.16+
Details | Diff | Splinter Review

Summon comment box

Description Jesse Ruderman 2009-09-10 16:21:54 PDT
Created attachment 399876 [details]
testcase (triggers assertion when closed)

###!!! ASSERTION: Some PresArena objects were not freed: 'mAllocCount == 0', file /Users/jruderman/central/layout/base/nsPresArena.cpp, line 169

Seems exploitable, but I'm not as sure as usual.
Comment 1 Timothy Nikkel (:tn) 2009-09-15 00:41:28 PDT
Created attachment 400699 [details] [review]
patch

I knew I should have listened to that nagging voice saying "what about the other early exit in ReflowBlockFrame?" from bug 513394.

When reflowing (the first continuation of) the div that is the child of the <div style="float: left; -moz-column-count: 3;"> (the div for short) we call ReflowBlockFrame on the <div style="clear: both;"> and it returns early, without setting mPrevChild because of this code

  if (!treatWithClearance && !applyTopMargin && mightClearFloats &&
      aState.mReflowState.mDiscoveredClearance) {
    nscoord curY = aState.mY + aState.mPrevBottomMargin.get();
    nscoord clearY = aState.ClearFloats(curY, breakType, replacedBlock);
    if (clearY != curY) {
      // Looks like that assumption was invalid, we do need
      // clearance. Tell our ancestor so it can reflow again. It is
      // responsible for actually setting our clearance flag before
      // the next reflow.
      treatWithClearance = PR_TRUE;
      // Only record the first frame that requires clearance
      if (!*aState.mReflowState.mDiscoveredClearance) {
        *aState.mReflowState.mDiscoveredClearance = frame;
      }
      // Exactly what we do now is flexible since we'll definitely be
      // reflowed.
      return NS_OK;
    }
  }

And then back in ReflowDirtyLines after the main loop over the lines is finished we check if we should pull lines with

  PRBool heightConstrained =
    aState.mReflowState.availableHeight != NS_UNCONSTRAINEDSIZE;
  PRBool skipPull = willReflowAgain && heightConstrained;

except aState.mReflowState.availableHeight has overflowed and is now unconstrained. So we end up pulling frames and mPrevChild is one back of where is should be for the pull.

The available height gets set to unconstrained in ReflowBlockFrame where we ComputeCollapsedTopMargin, and the topMargin is unconstrained because the huge font on the child <div id="x" style="margin: 1em 0pt;"> gives a huge margin. And then we do

    // Now put the Y coordinate back to the top of the top-margin +
    // clearance, and flow the block.
    aState.mY -= topMargin;
    availSpace.y -= topMargin;
    if (NS_UNCONSTRAINEDSIZE != availSpace.height) {
      availSpace.height += topMargin;
    }

so the available height becomes unconstrained.
Comment 2 fantasai 2009-09-22 11:39:35 PDT
Comment on attachment 400699 [details] [review]
patch

It looks reasonable to me, but I'd rather have dbaron, bz, or roc take a look here.
Comment 3 Jesse Ruderman 2009-10-20 12:28:02 PDT
WFM?  I'm suspicious, though, because bug 497495 part 4 moved this assertion.
Comment 4 Timothy Nikkel (:tn) 2009-10-20 15:54:52 PDT
The moving of the assertion in bug 497495 isn't to blame as I still get the (moved) assertion in a debug build at http://hg.mozilla.org/mozilla-central/rev/c655e28003ef which is after that landed.
Comment 5 Timothy Nikkel (:tn) 2009-10-20 17:07:36 PDT
Oh, it's due to the landing of bug 512471. At the end of ReflowDirtyLines it no longer depends on mPrevChild being set correctly so it doesn't fail.
Comment 6 Timothy Nikkel (:tn) 2009-10-20 17:13:00 PDT
I think it's still worth it to do this patch though.
Comment 7 Timothy Nikkel (:tn) 2009-10-20 23:31:21 PDT
Oh, and bug 512471 is not going to land on branches, so we'll need this patch for branches.
Comment 8 David Baron [:dbaron] 2009-11-03 14:50:56 PST
Comment on attachment 400699 [details] [review]
patch

sr=dbaron, although I'm not sure why we're going on and pulling frames (and reflowing more frames?) after we've already discovered we need to reflow again
Comment 9 Timothy Nikkel (:tn) 2009-11-04 01:47:39 PST
http://hg.mozilla.org/mozilla-central/rev/bb82129563af
Comment 10 Daniel Veditz 2009-11-04 15:31:27 PST
Comment on attachment 400699 [details] [review]
patch

Approved for 1.9.1.6 and 1.9.0.16, a=dveditz for release-drivers
Comment 11 Mike Shaver (:shaver) 2009-11-04 15:35:30 PST
Comment on attachment 400699 [details] [review]
patch

a=shaver for 1.9.2, thanks again timothy!
Comment 12 Timothy Nikkel (:tn) 2009-11-08 00:17:28 PST
http://hg.mozilla.org/releases/mozilla-1.9.2/rev/e0529f8ec04e
Comment 13 Timothy Nikkel (:tn) 2009-11-09 01:02:14 PST
http://hg.mozilla.org/releases/mozilla-1.9.1/rev/49e937c4a4db
Comment 14 Boris Zbarsky (:bz) 2009-11-09 09:20:10 PST
Checking in nsBlockFrame.cpp;
/cvsroot/mozilla/layout/generic/nsBlockFrame.cpp,v  <--  nsBlockFrame.cpp
new revision: 3.967; previous revision: 3.966
Comment 15 Al Billings [:abillings] 2009-11-20 11:57:27 PST
With debug 1.9.1 from before the fix, I don't see the assertion in comment 0. 
The only assert that I see that seems related, perhaps, is: 

###!!! ASSERTION: Some objects allocated with AllocateFrame were not freed: 'mFrameCount == 0', file /Users/albill/mozilla-191/layout/base/nsPresShell.cpp, line 674

With debug 1.9.0 before the fix, I see no assertion at all.

Is this just a defense in depth fix on 1.9.1 and 1.9.0 or were these assertions actually seen on these two branches?
Comment 16 Jesse Ruderman 2009-11-20 23:20:46 PST
That's the same assertion.  Its text changed at some point.
Comment 17 Al Billings [:abillings] 2009-11-21 08:14:25 PST
All right, so it is definitely fixed for 1.9.1. 

I don't see any assertion during 1.9.0 runs before the fix.

Note You need to log in before you can comment on or make changes to this bug.