Title: [143415] trunk/Source/WebCore
Revision
143415
Author
to...@chromium.org
Date
2013-02-19 17:20:48 -0800 (Tue, 19 Feb 2013)

Log Message

Fix crash in preloading scanning base tags with no href attribute for background parser
https://bugs.webkit.org/show_bug.cgi?id=110276

Reviewed by Eric Seidel.

Previously a <base> tag without an href attribute (like the one in fast/dom/HTMLAnchorElement/set-href-attribute-rebase.html)
would crash the background parser's preload scanner.

To fix that, we only call stripLeadingAndTrailingHTMLSpaces() if the href attribute is non-null. This matches the main thread parser.

Along with this, I decided to templatize updatePredictedBaseURL() so that the main and background parser can share the same impl.

This required making CompactHTMLToken and HTMLToken a little more similar:
1. Give HTMLToken a getAttributeItem() method.
2. Move CompactAttribute to CompactHTMLToken::Attribute and make it a struct.

No new tests because covered by existing tests.

* html/parser/AtomicHTMLToken.h:
(WebCore::AtomicHTMLToken::AtomicHTMLToken):
* html/parser/CompactHTMLToken.cpp:
(SameSizeAsCompactHTMLToken):
(WebCore::CompactHTMLToken::CompactHTMLToken):
(WebCore::CompactHTMLToken::getAttributeItem):
(WebCore::CompactHTMLToken::isSafeToSendToAnotherThread):
* html/parser/CompactHTMLToken.h:
(WebCore::CompactHTMLToken::Attribute::Attribute):
(Attribute):
(WebCore::CompactHTMLToken::attributes):
(CompactHTMLToken):
(WebCore::CompactHTMLToken::publicIdentifier):
(WebCore::CompactHTMLToken::systemIdentifier):
* html/parser/HTMLParserIdioms.h:
(WebCore):
(WebCore::stripLeadingAndTrailingHTMLSpaces):
* html/parser/HTMLPreloadScanner.cpp:
(WebCore::TokenPreloadScanner::StartTagScanner::processAttributes):
(WebCore):
(WebCore::TokenPreloadScanner::updatePredictedBaseURL):
* html/parser/HTMLPreloadScanner.h:
* html/parser/HTMLToken.h:
(WebCore::HTMLToken::getAttributeItem):
(HTMLToken):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (143414 => 143415)


--- trunk/Source/WebCore/ChangeLog	2013-02-20 01:18:24 UTC (rev 143414)
+++ trunk/Source/WebCore/ChangeLog	2013-02-20 01:20:48 UTC (rev 143415)
@@ -1,3 +1,49 @@
+2013-02-19  Tony Gentilcore  <to...@chromium.org>
+
+        Fix crash in preloading scanning base tags with no href attribute for background parser
+        https://bugs.webkit.org/show_bug.cgi?id=110276
+
+        Reviewed by Eric Seidel.
+
+        Previously a <base> tag without an href attribute (like the one in fast/dom/HTMLAnchorElement/set-href-attribute-rebase.html)
+        would crash the background parser's preload scanner.
+
+        To fix that, we only call stripLeadingAndTrailingHTMLSpaces() if the href attribute is non-null. This matches the main thread parser.
+
+        Along with this, I decided to templatize updatePredictedBaseURL() so that the main and background parser can share the same impl.
+
+        This required making CompactHTMLToken and HTMLToken a little more similar:
+        1. Give HTMLToken a getAttributeItem() method.
+        2. Move CompactAttribute to CompactHTMLToken::Attribute and make it a struct.
+
+        No new tests because covered by existing tests.
+
+        * html/parser/AtomicHTMLToken.h:
+        (WebCore::AtomicHTMLToken::AtomicHTMLToken):
+        * html/parser/CompactHTMLToken.cpp:
+        (SameSizeAsCompactHTMLToken):
+        (WebCore::CompactHTMLToken::CompactHTMLToken):
+        (WebCore::CompactHTMLToken::getAttributeItem):
+        (WebCore::CompactHTMLToken::isSafeToSendToAnotherThread):
+        * html/parser/CompactHTMLToken.h:
+        (WebCore::CompactHTMLToken::Attribute::Attribute):
+        (Attribute):
+        (WebCore::CompactHTMLToken::attributes):
+        (CompactHTMLToken):
+        (WebCore::CompactHTMLToken::publicIdentifier):
+        (WebCore::CompactHTMLToken::systemIdentifier):
+        * html/parser/HTMLParserIdioms.h:
+        (WebCore):
+        (WebCore::stripLeadingAndTrailingHTMLSpaces):
+        * html/parser/HTMLPreloadScanner.cpp:
+        (WebCore::TokenPreloadScanner::StartTagScanner::processAttributes):
+        (WebCore):
+        (WebCore::TokenPreloadScanner::updatePredictedBaseURL):
+        * html/parser/HTMLPreloadScanner.h:
+        * html/parser/HTMLToken.h:
+        (WebCore::HTMLToken::getAttributeItem):
+        (HTMLToken):
+
 2013-02-19  Mark Lam  <mark....@apple.com>
 
         Introducing AbstractSQLTransaction and AbstractSQLTransactionBackend.

Modified: trunk/Source/WebCore/html/parser/AtomicHTMLToken.h (143414 => 143415)


--- trunk/Source/WebCore/html/parser/AtomicHTMLToken.h	2013-02-20 01:18:24 UTC (rev 143414)
+++ trunk/Source/WebCore/html/parser/AtomicHTMLToken.h	2013-02-20 01:20:48 UTC (rev 143415)
@@ -201,8 +201,8 @@
             break;
         case HTMLToken::StartTag:
             m_attributes.reserveInitialCapacity(token.attributes().size());
-            for (Vector<CompactAttribute>::const_iterator it = token.attributes().begin(); it != token.attributes().end(); ++it)
-                m_attributes.append(Attribute(QualifiedName(nullAtom, it->name(), nullAtom), it->value()));
+            for (Vector<CompactHTMLToken::Attribute>::const_iterator it = token.attributes().begin(); it != token.attributes().end(); ++it)
+                m_attributes.append(Attribute(QualifiedName(nullAtom, it->name, nullAtom), it->value));
             // Fall through!
         case HTMLToken::EndTag:
             m_selfClosing = token.selfClosing();

Modified: trunk/Source/WebCore/html/parser/CompactHTMLToken.cpp (143414 => 143415)


--- trunk/Source/WebCore/html/parser/CompactHTMLToken.cpp	2013-02-20 01:18:24 UTC (rev 143414)
+++ trunk/Source/WebCore/html/parser/CompactHTMLToken.cpp	2013-02-20 01:20:48 UTC (rev 143415)
@@ -39,7 +39,7 @@
 struct SameSizeAsCompactHTMLToken  {
     unsigned bitfields;
     String name;
-    Vector<CompactAttribute> vector;
+    Vector<Attribute> vector;
     TextPosition textPosition;
     OwnPtr<XSSInfo> xssInfo;
 };
@@ -60,7 +60,7 @@
         m_data = String(token->name());
         // There is only 1 DOCTYPE token per document, so to avoid increasing the
         // size of CompactHTMLToken, we just use the m_attributes vector.
-        m_attributes.append(CompactAttribute(String(token->publicIdentifier()), String(token->systemIdentifier())));
+        m_attributes.append(Attribute(String(token->publicIdentifier()), String(token->systemIdentifier())));
         m_doctypeForcesQuirks = token->forceQuirks();
         break;
     }
@@ -70,7 +70,7 @@
         m_attributes.reserveInitialCapacity(token->attributes().size());
         // FIXME: Attribute names and values should be 8bit when possible.
         for (Vector<HTMLToken::Attribute>::const_iterator it = token->attributes().begin(); it != token->attributes().end(); ++it)
-            m_attributes.append(CompactAttribute(String(it->name), String(it->value)));
+            m_attributes.append(Attribute(String(it->name), String(it->value)));
         // Fall through!
     case HTMLToken::EndTag:
         m_selfClosing = token->selfClosing();
@@ -102,10 +102,10 @@
         m_xssInfo = adoptPtr(new XSSInfo(*other.m_xssInfo));
 }
 
-const CompactAttribute* CompactHTMLToken::getAttributeItem(const QualifiedName& name) const
+const CompactHTMLToken::Attribute* CompactHTMLToken::getAttributeItem(const QualifiedName& name) const
 {
     for (unsigned i = 0; i < m_attributes.size(); ++i) {
-        if (threadSafeMatch(m_attributes.at(i).name(), name))
+        if (threadSafeMatch(m_attributes.at(i).name, name))
             return &m_attributes.at(i);
     }
     return 0;
@@ -113,10 +113,10 @@
 
 bool CompactHTMLToken::isSafeToSendToAnotherThread() const
 {
-    for (Vector<CompactAttribute>::const_iterator it = m_attributes.begin(); it != m_attributes.end(); ++it) {
-        if (!it->name().isSafeToSendToAnotherThread())
+    for (Vector<Attribute>::const_iterator it = m_attributes.begin(); it != m_attributes.end(); ++it) {
+        if (!it->name.isSafeToSendToAnotherThread())
             return false;
-        if (!it->value().isSafeToSendToAnotherThread())
+        if (!it->value.isSafeToSendToAnotherThread())
             return false;
     }
     if (m_xssInfo && !m_xssInfo->isSafeToSendToAnotherThread())

Modified: trunk/Source/WebCore/html/parser/CompactHTMLToken.h (143414 => 143415)


--- trunk/Source/WebCore/html/parser/CompactHTMLToken.h	2013-02-20 01:18:24 UTC (rev 143414)
+++ trunk/Source/WebCore/html/parser/CompactHTMLToken.h	2013-02-20 01:20:48 UTC (rev 143415)
@@ -42,24 +42,19 @@
 class QualifiedName;
 class XSSInfo;
 
-class CompactAttribute {
+class CompactHTMLToken {
 public:
-    CompactAttribute(const String& name, const String& value)
-        : m_name(name)
-        , m_value(value)
-    {
-    }
+    struct Attribute {
+        Attribute(const String& name, const String& value)
+            : name(name)
+            , value(value)
+        {
+        }
 
-    const String& name() const { return m_name; }
-    const String& value() const { return m_value; }
+        String name;
+        String value;
+    };
 
-private:
-    String m_name;
-    String m_value;
-};
-
-class CompactHTMLToken {
-public:
     CompactHTMLToken(const HTMLToken*, const TextPosition&);
     CompactHTMLToken(const CompactHTMLToken&);
 
@@ -69,14 +64,14 @@
     const String& data() const { return m_data; }
     bool selfClosing() const { return m_selfClosing; }
     bool isAll8BitData() const { return m_isAll8BitData; }
-    const Vector<CompactAttribute>& attributes() const { return m_attributes; }
-    const CompactAttribute* getAttributeItem(const QualifiedName&) const;
+    const Vector<Attribute>& attributes() const { return m_attributes; }
+    const Attribute* getAttributeItem(const QualifiedName&) const;
     const TextPosition& textPosition() const { return m_textPosition; }
 
     // There is only 1 DOCTYPE token per document, so to avoid increasing the
     // size of CompactHTMLToken, we just use the m_attributes vector.
-    const String& publicIdentifier() const { return m_attributes[0].name(); }
-    const String& systemIdentifier() const { return m_attributes[0].value(); }
+    const String& publicIdentifier() const { return m_attributes[0].name; }
+    const String& systemIdentifier() const { return m_attributes[0].value; }
     bool doctypeForcesQuirks() const { return m_doctypeForcesQuirks; }
     XSSInfo* xssInfo() const;
     void setXSSInfo(PassOwnPtr<XSSInfo>);
@@ -88,7 +83,7 @@
     unsigned m_doctypeForcesQuirks: 1;
 
     String m_data; // "name", "characters", or "data" depending on m_type
-    Vector<CompactAttribute> m_attributes;
+    Vector<Attribute> m_attributes;
     TextPosition m_textPosition;
     OwnPtr<XSSInfo> m_xssInfo;
 };

Modified: trunk/Source/WebCore/html/parser/HTMLParserIdioms.h (143414 => 143415)


--- trunk/Source/WebCore/html/parser/HTMLParserIdioms.h	2013-02-20 01:18:24 UTC (rev 143414)
+++ trunk/Source/WebCore/html/parser/HTMLParserIdioms.h	2013-02-20 01:20:48 UTC (rev 143415)
@@ -26,6 +26,7 @@
 #define HTMLParserIdioms_h
 
 #include <wtf/Forward.h>
+#include <wtf/text/WTFString.h>
 #include <wtf/unicode/Unicode.h>
 
 namespace WebCore {
@@ -40,6 +41,11 @@
 
 // Strip leading and trailing whitespace as defined by the HTML specification. 
 String stripLeadingAndTrailingHTMLSpaces(const String&);
+template<size_t inlineCapacity>
+String stripLeadingAndTrailingHTMLSpaces(const Vector<UChar, inlineCapacity>& vector)
+{
+    return stripLeadingAndTrailingHTMLSpaces(StringImpl::create8BitIfPossible(vector));
+}
 
 // An implementation of the HTML specification's algorithm to convert a number to a string for number and range types.
 String serializeForNumberType(const Decimal&);

Modified: trunk/Source/WebCore/html/parser/HTMLPreloadScanner.cpp (143414 => 143415)


--- trunk/Source/WebCore/html/parser/HTMLPreloadScanner.cpp	2013-02-20 01:18:24 UTC (rev 143414)
+++ trunk/Source/WebCore/html/parser/HTMLPreloadScanner.cpp	2013-02-20 01:20:48 UTC (rev 143415)
@@ -127,12 +127,12 @@
     }
 
 #if ENABLE(THREADED_HTML_PARSER)
-    void processAttributes(const Vector<CompactAttribute>& attributes)
+    void processAttributes(const Vector<CompactHTMLToken::Attribute>& attributes)
     {
         if (m_tagId >= UnknownTagId)
             return;
-        for (Vector<CompactAttribute>::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter)
-            processAttribute(iter->name(), iter->value());
+        for (Vector<CompactHTMLToken::Attribute>::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter)
+            processAttribute(iter->name, iter->value);
     }
 #endif
 
@@ -337,27 +337,14 @@
     }
 }
 
-void TokenPreloadScanner::updatePredictedBaseURL(const HTMLToken& token)
+template<typename Token>
+void TokenPreloadScanner::updatePredictedBaseURL(const Token& token)
 {
     ASSERT(m_predictedBaseElementURL.isEmpty());
-    for (HTMLToken::AttributeList::const_iterator iter = token.attributes().begin(); iter != token.attributes().end(); ++iter) {
-        AtomicString attributeName(iter->name);
-        if (attributeName == hrefAttr) {
-            String hrefValue = StringImpl::create8BitIfPossible(iter->value);
-            m_predictedBaseElementURL = KURL(m_documentURL, stripLeadingAndTrailingHTMLSpaces(hrefValue));
-            break;
-        }
-    }
+    if (const typename Token::Attribute* hrefAttribute = token.getAttributeItem(hrefAttr))
+        m_predictedBaseElementURL = KURL(m_documentURL, stripLeadingAndTrailingHTMLSpaces(hrefAttribute->value)).copy();
 }
 
-#if ENABLE(THREADED_HTML_PARSER)
-void TokenPreloadScanner::updatePredictedBaseURL(const CompactHTMLToken& token)
-{
-    ASSERT(m_predictedBaseElementURL.isEmpty());
-    m_predictedBaseElementURL = KURL(m_documentURL, stripLeadingAndTrailingHTMLSpaces(token.getAttributeItem(hrefAttr)->value())).copy();
-}
-#endif
-
 HTMLPreloadScanner::HTMLPreloadScanner(const HTMLParserOptions& options, const KURL& documentURL)
     : m_scanner(documentURL)
     , m_tokenizer(HTMLTokenizer::create(options))

Modified: trunk/Source/WebCore/html/parser/HTMLPreloadScanner.h (143414 => 143415)


--- trunk/Source/WebCore/html/parser/HTMLPreloadScanner.h	2013-02-20 01:18:24 UTC (rev 143414)
+++ trunk/Source/WebCore/html/parser/HTMLPreloadScanner.h	2013-02-20 01:20:48 UTC (rev 143415)
@@ -82,10 +82,8 @@
 
     static String initiatorFor(TagId);
 
-    void updatePredictedBaseURL(const HTMLToken&);
-#if ENABLE(THREADED_HTML_PARSER)
-    void updatePredictedBaseURL(const CompactHTMLToken&);
-#endif
+    template<typename Token>
+    void updatePredictedBaseURL(const Token&);
 
     CSSPreloadScanner m_cssScanner;
     KURL m_documentURL;

Modified: trunk/Source/WebCore/html/parser/HTMLToken.h (143414 => 143415)


--- trunk/Source/WebCore/html/parser/HTMLToken.h	2013-02-20 01:18:24 UTC (rev 143414)
+++ trunk/Source/WebCore/html/parser/HTMLToken.h	2013-02-20 01:20:48 UTC (rev 143415)
@@ -358,6 +358,15 @@
         return m_attributes;
     }
 
+    const Attribute* getAttributeItem(const QualifiedName& name) const
+    {
+        for (unsigned i = 0; i < m_attributes.size(); ++i) {
+            if (AtomicString(m_attributes.at(i).name) == name.localName())
+                return &m_attributes.at(i);
+        }
+        return 0;
+    }
+
     // Used by the XSSAuditor to nuke XSS-laden attributes.
     void eraseValueOfAttribute(size_t i)
     {
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to