Changeset 62033 in webkit


Ignore:
Timestamp:
Jun 28, 2010 1:30:32 PM (14 years ago)
Author:
abarth@webkit.org
Message:

2010-06-28 Adam Barth <abarth@webkit.org>

Reviewed by Eric Seidel.

HTML5 Regression: Crash in insert()
https://bugs.webkit.org/show_bug.cgi?id=41281

We need to call endIfDelayed() outside of the script nesting block
because endIfDelayed() might call end(), which deletes the
HTMLDocumentParser. If we try to exit the script nesting block after
the HTMLDocumentParser has been deleted, we'll decrement unallocated
memory, which is bad times.

Moving endIfDelayed outside of the script nesting block also lets us
avoid ending if inWrite() is true. If we're inWrite(), then there's
folks above us on the stack who will crash of the HTMLDocumentParser is
deallocated. Adding this check matches the LegacyHTMLDocumentParser
and the logic in attemptToEnd, facilitating a small refactoring of the
common logic for improved readability.

I don't know of any test case that changes in behavior because of this
patch, but this bug exists on the same line of code that the reliablity
tests crashed. I'm not sure whether this patch will fix that crash,
but removing bugs (even theoretical ones) seems like a good idea.

  • html/HTMLDocumentParser.cpp: (WebCore::HTMLDocumentParser::insert): (WebCore::HTMLDocumentParser::append): (WebCore::HTMLDocumentParser::attemptToEnd): (WebCore::HTMLDocumentParser::endIfDelayed): (WebCore::HTMLDocumentParser::resumeParsingAfterScriptExecution):
  • html/HTMLDocumentParser.h: (WebCore::HTMLDocumentParser::shouldDelayEnd):
Location:
trunk/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r62030 r62033  
     12010-06-28  Adam Barth  <abarth@webkit.org>
     2
     3        Reviewed by Eric Seidel.
     4
     5        HTML5 Regression: Crash in insert()
     6        https://bugs.webkit.org/show_bug.cgi?id=41281
     7
     8        We need to call endIfDelayed() outside of the script nesting block
     9        because endIfDelayed() might call end(), which deletes the
     10        HTMLDocumentParser.  If we try to exit the script nesting block after
     11        the HTMLDocumentParser has been deleted, we'll decrement unallocated
     12        memory, which is bad times.
     13
     14        Moving endIfDelayed outside of the script nesting block also lets us
     15        avoid ending if inWrite() is true.  If we're inWrite(), then there's
     16        folks above us on the stack who will crash of the HTMLDocumentParser is
     17        deallocated.  Adding this check matches the LegacyHTMLDocumentParser
     18        and the logic in attemptToEnd, facilitating a small refactoring of the
     19        common logic for improved readability.
     20
     21        I don't know of any test case that changes in behavior because of this
     22        patch, but this bug exists on the same line of code that the reliablity
     23        tests crashed.  I'm not sure whether this patch will fix that crash,
     24        but removing bugs (even theoretical ones) seems like a good idea.
     25
     26        * html/HTMLDocumentParser.cpp:
     27        (WebCore::HTMLDocumentParser::insert):
     28        (WebCore::HTMLDocumentParser::append):
     29        (WebCore::HTMLDocumentParser::attemptToEnd):
     30        (WebCore::HTMLDocumentParser::endIfDelayed):
     31        (WebCore::HTMLDocumentParser::resumeParsingAfterScriptExecution):
     32        * html/HTMLDocumentParser.h:
     33        (WebCore::HTMLDocumentParser::shouldDelayEnd):
     34
    1352010-06-28  Eric Carlson  <eric.carlson@apple.com>
    236
  • trunk/WebCore/html/HTMLDocumentParser.cpp

    r61985 r62033  
    219219        return;
    220220
    221     NestingLevelIncrementer nestingLevelIncrementer(m_writeNestingLevel);
    222 
    223     SegmentedString excludedLineNumberSource(source);
    224     excludedLineNumberSource.setExcludeLineNumbers();
    225     m_input.insertAtCurrentInsertionPoint(excludedLineNumberSource);
    226     pumpTokenizerIfPossible(ForceSynchronous);
     221    {
     222        NestingLevelIncrementer nestingLevelIncrementer(m_writeNestingLevel);
     223
     224        SegmentedString excludedLineNumberSource(source);
     225        excludedLineNumberSource.setExcludeLineNumbers();
     226        m_input.insertAtCurrentInsertionPoint(excludedLineNumberSource);
     227        pumpTokenizerIfPossible(ForceSynchronous);
     228    }
     229
    227230    endIfDelayed();
    228231}
     
    233236        return;
    234237
    235     NestingLevelIncrementer nestingLevelIncrementer(m_writeNestingLevel);
    236 
    237     m_input.appendToEnd(source);
    238     if (m_preloadScanner)
    239         m_preloadScanner->appendToEnd(source);
    240 
    241     if (m_writeNestingLevel > 1) {
    242         // We've gotten data off the network in a nested write.
    243         // We don't want to consume any more of the input stream now.  Do
    244         // not worry.  We'll consume this data in a less-nested write().
    245         return;
    246     }
    247 
    248     pumpTokenizerIfPossible(AllowYield);
     238    {
     239        NestingLevelIncrementer nestingLevelIncrementer(m_writeNestingLevel);
     240
     241        m_input.appendToEnd(source);
     242        if (m_preloadScanner)
     243            m_preloadScanner->appendToEnd(source);
     244
     245        if (m_writeNestingLevel > 1) {
     246            // We've gotten data off the network in a nested write.
     247            // We don't want to consume any more of the input stream now.  Do
     248            // not worry.  We'll consume this data in a less-nested write().
     249            return;
     250        }
     251
     252        pumpTokenizerIfPossible(AllowYield);
     253    }
     254
    249255    endIfDelayed();
    250256}
     
    266272    // an external script to load, we can't finish parsing quite yet.
    267273
    268     if (inWrite() || isWaitingForScripts() || inScriptExecution() || isScheduledForResume()) {
     274    if (shouldDelayEnd()) {
    269275        m_endWasDelayed = true;
    270276        return;
     
    275281void HTMLDocumentParser::endIfDelayed()
    276282{
    277     // We don't check inWrite() here since inWrite() will be true if this was
    278     // called from write().
    279     if (!m_endWasDelayed || isWaitingForScripts() || inScriptExecution() || isScheduledForResume())
     283    if (!m_endWasDelayed || shouldDelayEnd())
    280284        return;
    281285
     
    337341
    338342    pumpTokenizerIfPossible(AllowYield);
    339 
    340     // The document already finished parsing we were just waiting on scripts when finished() was called.
    341343    endIfDelayed();
    342344}
  • trunk/WebCore/html/HTMLDocumentParser.h

    r61985 r62033  
    110110    bool inScriptExecution() const;
    111111    bool inWrite() const { return m_writeNestingLevel > 0; }
     112    bool shouldDelayEnd() const { return inWrite() || isWaitingForScripts() || inScriptExecution() || isScheduledForResume(); }
    112113
    113114    ScriptController* script() const;
Note: See TracChangeset for help on using the changeset viewer.