Changeset 60802 in webkit


Ignore:
Timestamp:
Jun 7, 2010, 2:53:13 PM (15 years ago)
Author:
abarth@webkit.org
Message:

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

Reviewed by Eric Seidel.

Fix XFrameOptions and xssAuditor crashes in HTML5 parser
https://bugs.webkit.org/show_bug.cgi?id=40265

We're not supposed to call end() while the tokenizer's write() method.
This causes a bunch of LayoutTests to crash. In particular, this patch
fixes crashes in the following tests:

Tests:

  • http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag-in-body.html
  • http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag-parent-same-origin-deny.html
  • http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag.html
  • http/tests/security/xssAuditor/full-block-base-href.html
  • http/tests/security/xssAuditor/full-block-get-from-iframe.html
  • http/tests/security/xssAuditor/full-block-iframe-javascript-url.html
  • http/tests/security/xssAuditor/full-block-link-onclick.html
  • http/tests/security/xssAuditor/full-block-post-from-iframe.html
  • http/tests/security/xssAuditor/full-block-script-tag.html
  • http/tests/security/xssAuditor/xss-protection-parsing-01.html
  • html/HTML5Tokenizer.cpp: (WebCore::): (WebCore::HTML5Tokenizer::HTML5Tokenizer): (WebCore::HTML5Tokenizer::write): (WebCore::HTML5Tokenizer::attemptToEnd): (WebCore::HTML5Tokenizer::endIfDelayed): (WebCore::HTML5Tokenizer::finish): (WebCore::HTML5Tokenizer::resumeParsingAfterScriptExecution):
  • html/HTML5Tokenizer.h: (WebCore::HTML5Tokenizer::inWrite):
Location:
trunk/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r60801 r60802  
     12010-06-07  Adam Barth  <abarth@webkit.org>
     2
     3        Reviewed by Eric Seidel.
     4
     5        Fix XFrameOptions and xssAuditor crashes in HTML5 parser
     6        https://bugs.webkit.org/show_bug.cgi?id=40265
     7
     8        We're not supposed to call end() while the tokenizer's write() method.
     9        This causes a bunch of LayoutTests to crash.  In particular, this patch
     10        fixes crashes in the following tests:
     11
     12        Tests:
     13          * http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag-in-body.html
     14          * http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag-parent-same-origin-deny.html
     15          * http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag.html
     16          * http/tests/security/xssAuditor/full-block-base-href.html
     17          * http/tests/security/xssAuditor/full-block-get-from-iframe.html
     18          * http/tests/security/xssAuditor/full-block-iframe-javascript-url.html
     19          * http/tests/security/xssAuditor/full-block-link-onclick.html
     20          * http/tests/security/xssAuditor/full-block-post-from-iframe.html
     21          * http/tests/security/xssAuditor/full-block-script-tag.html
     22          * http/tests/security/xssAuditor/xss-protection-parsing-01.html
     23
     24        * html/HTML5Tokenizer.cpp:
     25        (WebCore::):
     26        (WebCore::HTML5Tokenizer::HTML5Tokenizer):
     27        (WebCore::HTML5Tokenizer::write):
     28        (WebCore::HTML5Tokenizer::attemptToEnd):
     29        (WebCore::HTML5Tokenizer::endIfDelayed):
     30        (WebCore::HTML5Tokenizer::finish):
     31        (WebCore::HTML5Tokenizer::resumeParsingAfterScriptExecution):
     32        * html/HTML5Tokenizer.h:
     33        (WebCore::HTML5Tokenizer::inWrite):
     34
    1352010-06-07  Eric Seidel  <eric@webkit.org>
    236
  • trunk/WebCore/html/HTML5Tokenizer.cpp

    r60801 r60802  
    3838namespace WebCore {
    3939
     40namespace {
     41
     42class NestingLevelIncrementer : public Noncopyable {
     43public:
     44    NestingLevelIncrementer(int& counter)
     45        : m_counter(&counter)
     46    {
     47        ++(*m_counter);
     48    }
     49   
     50    ~NestingLevelIncrementer()
     51    {
     52        --(*m_counter);
     53    }
     54
     55private:
     56    int* m_counter;
     57};
     58
     59} // namespace
     60
    4061HTML5Tokenizer::HTML5Tokenizer(HTMLDocument* document, bool reportErrors)
    4162    : Tokenizer()
     
    4465    , m_scriptRunner(new HTML5ScriptRunner(document, this))
    4566    , m_treeBuilder(new HTML5TreeBuilder(m_lexer.get(), document, reportErrors))
    46     , m_wasWaitingOnScriptsDuringFinish(false)
     67    , m_endWasDelayed(false)
     68    , m_writeNestingLevel(0)
    4769{
    4870    begin();
     
    5173HTML5Tokenizer::~HTML5Tokenizer()
    5274{
     75    ASSERT(!m_endWasDelayed);
    5376}
    5477
     
    81104void HTML5Tokenizer::write(const SegmentedString& source, bool)
    82105{
     106    NestingLevelIncrementer nestingLevelIncrementer(m_writeNestingLevel);
     107
    83108    // HTML5Tokenizer::executeScript is responsible for handling saving m_source before re-entry.
    84109    m_source.append(source);
    85110    if (!m_treeBuilder->isPaused())
    86111        pumpLexer();
     112
     113    endIfDelayed();
    87114}
    88115
     
    95122}
    96123
    97 void HTML5Tokenizer::finish()
     124void HTML5Tokenizer::attemptToEnd()
    98125{
    99126    // finish() indicates we will not receive any more data. If we are waiting on
    100127    // an external script to load, we can't finish parsing quite yet.
    101     if (isWaitingForScripts()) {
    102         // FIXME: We might want to use real state enum instead of a bool here.
    103         m_wasWaitingOnScriptsDuringFinish = true;
    104         return;
    105     }
     128
     129    if (inWrite() || isWaitingForScripts()) {
     130        m_endWasDelayed = true;
     131        return;
     132    }
     133
    106134    // We can't call m_source.close() yet as we may have a <script> execution
    107135    // pending which will call document.write().  No more data off the network though.
    108136    end();
     137}
     138
     139void HTML5Tokenizer::endIfDelayed()
     140{
     141    if (!m_endWasDelayed || !m_source.isEmpty() || isWaitingForScripts() || executingScript())
     142        return;
     143
     144    m_endWasDelayed = false;
     145    end();
     146}
     147
     148void HTML5Tokenizer::finish()
     149{
     150    attemptToEnd();
    109151}
    110152
     
    135177    pumpLexer();
    136178    ASSERT(m_treeBuilder->isPaused() || m_source.isEmpty());
    137     if (m_source.isEmpty() && m_wasWaitingOnScriptsDuringFinish)
    138         end(); // The document already finished parsing we were just waiting on scripts when finished() was called.
     179    // The document already finished parsing we were just waiting on scripts when finished() was called.
     180    endIfDelayed();
    139181}
    140182
  • trunk/WebCore/html/HTML5Tokenizer.h

    r60553 r60802  
    7373    void resumeParsingAfterScriptExecution();
    7474
     75    void attemptToEnd();
     76    void endIfDelayed();
     77    bool inWrite() const { return m_writeNestingLevel > 0; }
     78
    7579    SegmentedString m_source;
    7680
     
    8286    OwnPtr<HTML5ScriptRunner> m_scriptRunner;
    8387    OwnPtr<HTML5TreeBuilder> m_treeBuilder;
    84     bool m_wasWaitingOnScriptsDuringFinish;
     88    bool m_endWasDelayed;
     89    int m_writeNestingLevel;
    8590};
    8691
Note: See TracChangeset for help on using the changeset viewer.