Title: [237909] trunk/Source/WebCore
Revision
237909
Author
[email protected]
Date
2018-11-06 19:12:18 -0800 (Tue, 06 Nov 2018)

Log Message

Post too much text to iFrame could crash webkit
https://bugs.webkit.org/show_bug.cgi?id=190947
<rdar://problem/45678231>

Reviewed by Geoffrey Garen.

Optimize SuffixTree (Which is used by XSSAuditor) to stop storing each Node's
children as a static array of 128 pointers and use a dynamic array (vector)
instead. This uses way less memory. Also make SuffixTree and SuffixTree::Node
as fast allocated for performance. This part of the change is based on the
following Blink change:
- https://chromium.googlesource.com/chromium/src.git/+/6ca590e1c7edaa7c56cac9e3e3c39cf398ca8d4d

Also update the XSSAuditor to construct the SuffixTree lazily since there are
many cases (including the one in this bug) where we were spending a significant
amount of time building the SuffixTree and then never querying it.

* html/parser/XSSAuditor.cpp:
(WebCore::XSSAuditor::init):
(WebCore::XSSAuditor::decodedHTTPBodySuffixTree):
(WebCore::XSSAuditor::isContainedInRequest):
* html/parser/XSSAuditor.h:
* platform/text/SuffixTree.h:
(WebCore::SuffixTree::mightContain):
(WebCore::SuffixTree::Node::Node):
(WebCore::SuffixTree::Node::~Node):
(WebCore::SuffixTree::Node::find):
(WebCore::SuffixTree::Node::end):
(WebCore::SuffixTree::build):
(WebCore::SuffixTree<Codebook>::Node::childAt):
(WebCore::SuffixTree::Node::at): Deleted.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (237908 => 237909)


--- trunk/Source/WebCore/ChangeLog	2018-11-07 02:31:30 UTC (rev 237908)
+++ trunk/Source/WebCore/ChangeLog	2018-11-07 03:12:18 UTC (rev 237909)
@@ -1,3 +1,37 @@
+2018-11-06  Chris Dumez  <[email protected]>
+
+        Post too much text to iFrame could crash webkit
+        https://bugs.webkit.org/show_bug.cgi?id=190947
+        <rdar://problem/45678231>
+
+        Reviewed by Geoffrey Garen.
+
+        Optimize SuffixTree (Which is used by XSSAuditor) to stop storing each Node's
+        children as a static array of 128 pointers and use a dynamic array (vector)
+        instead. This uses way less memory. Also make SuffixTree and SuffixTree::Node
+        as fast allocated for performance. This part of the change is based on the
+        following Blink change:
+        - https://chromium.googlesource.com/chromium/src.git/+/6ca590e1c7edaa7c56cac9e3e3c39cf398ca8d4d
+
+        Also update the XSSAuditor to construct the SuffixTree lazily since there are
+        many cases (including the one in this bug) where we were spending a significant
+        amount of time building the SuffixTree and then never querying it.
+
+        * html/parser/XSSAuditor.cpp:
+        (WebCore::XSSAuditor::init):
+        (WebCore::XSSAuditor::decodedHTTPBodySuffixTree):
+        (WebCore::XSSAuditor::isContainedInRequest):
+        * html/parser/XSSAuditor.h:
+        * platform/text/SuffixTree.h:
+        (WebCore::SuffixTree::mightContain):
+        (WebCore::SuffixTree::Node::Node):
+        (WebCore::SuffixTree::Node::~Node):
+        (WebCore::SuffixTree::Node::find):
+        (WebCore::SuffixTree::Node::end):
+        (WebCore::SuffixTree::build):
+        (WebCore::SuffixTree<Codebook>::Node::childAt):
+        (WebCore::SuffixTree::Node::at): Deleted.
+
 2018-11-06  Youenn Fablet  <[email protected]>
 
         Support onremovetrack for RTCPeerConnection removed tracks

Modified: trunk/Source/WebCore/html/parser/XSSAuditor.cpp (237908 => 237909)


--- trunk/Source/WebCore/html/parser/XSSAuditor.cpp	2018-11-07 02:31:30 UTC (rev 237908)
+++ trunk/Source/WebCore/html/parser/XSSAuditor.cpp	2018-11-07 03:12:18 UTC (rev 237909)
@@ -274,9 +274,6 @@
 
 void XSSAuditor::init(Document* document, XSSAuditorDelegate* auditorDelegate)
 {
-    const size_t minimumLengthForSuffixTree = 512; // FIXME: Tune this parameter.
-    const int suffixTreeDepth = 5;
-
     ASSERT(isMainThread());
     if (m_state == Initialized)
         return;
@@ -316,7 +313,6 @@
     if (m_decodedURL.find(isRequiredForInjection) == notFound)
         m_decodedURL = String();
 
-    String httpBodyAsString;
     if (RefPtr<DocumentLoader> documentLoader = document->frame()->loader().documentLoader()) {
         String headerValue = documentLoader->response().httpHeaderField(HTTPHeaderName::XXSSProtection);
         String errorDetails;
@@ -344,13 +340,11 @@
             auditorDelegate->setReportURL(reportURL.isolatedCopy());
         RefPtr<FormData> httpBody = documentLoader->originalRequest().httpBody();
         if (httpBody && !httpBody->isEmpty()) {
-            httpBodyAsString = httpBody->flattenToString();
+            String httpBodyAsString = httpBody->flattenToString();
             if (!httpBodyAsString.isEmpty()) {
                 m_decodedHTTPBody = canonicalize(httpBodyAsString, TruncationStyle::None);
                 if (m_decodedHTTPBody.find(isRequiredForInjection) == notFound)
                     m_decodedHTTPBody = String();
-                if (m_decodedHTTPBody.length() >= minimumLengthForSuffixTree)
-                    m_decodedHTTPBodySuffixTree = std::make_unique<SuffixTree<ASCIICodebook>>(m_decodedHTTPBody, suffixTreeDepth);
             }
         }
     }
@@ -711,6 +705,16 @@
     return result;
 }
 
+SuffixTree<ASCIICodebook>* XSSAuditor::decodedHTTPBodySuffixTree()
+{
+    const unsigned minimumLengthForSuffixTree = 512; // FIXME: Tune this parameter.
+    const unsigned suffixTreeDepth = 5;
+
+    if (!m_decodedHTTPBodySuffixTree && m_decodedHTTPBody.length() >= minimumLengthForSuffixTree)
+        m_decodedHTTPBodySuffixTree = std::make_unique<SuffixTree<ASCIICodebook>>(m_decodedHTTPBody, suffixTreeDepth);
+    return m_decodedHTTPBodySuffixTree.get();
+}
+
 bool XSSAuditor::isContainedInRequest(const String& decodedSnippet)
 {
     if (decodedSnippet.isEmpty())
@@ -717,7 +721,8 @@
         return false;
     if (m_decodedURL.containsIgnoringASCIICase(decodedSnippet))
         return true;
-    if (m_decodedHTTPBodySuffixTree && !m_decodedHTTPBodySuffixTree->mightContain(decodedSnippet))
+    auto* decodedHTTPBodySuffixTree = this->decodedHTTPBodySuffixTree();
+    if (decodedHTTPBodySuffixTree && !decodedHTTPBodySuffixTree->mightContain(decodedSnippet))
         return false;
     return m_decodedHTTPBody.containsIgnoringASCIICase(decodedSnippet);
 }

Modified: trunk/Source/WebCore/html/parser/XSSAuditor.h (237908 => 237909)


--- trunk/Source/WebCore/html/parser/XSSAuditor.h	2018-11-07 02:31:30 UTC (rev 237908)
+++ trunk/Source/WebCore/html/parser/XSSAuditor.h	2018-11-07 03:12:18 UTC (rev 237909)
@@ -102,6 +102,8 @@
     bool isContainedInRequest(const String&);
     bool isLikelySafeResource(const String& url);
 
+    SuffixTree<ASCIICodebook>* decodedHTTPBodySuffixTree();
+
     URL m_documentURL;
     bool m_isEnabled;
 

Modified: trunk/Source/WebCore/platform/text/SuffixTree.h (237908 => 237909)


--- trunk/Source/WebCore/platform/text/SuffixTree.h	2018-11-07 02:31:30 UTC (rev 237908)
+++ trunk/Source/WebCore/platform/text/SuffixTree.h	2018-11-07 03:12:18 UTC (rev 237909)
@@ -23,8 +23,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef SuffixTree_h
-#define SuffixTree_h
+#pragma once
 
 #include <wtf/Vector.h>
 #include <wtf/text/WTFString.h>
@@ -45,6 +44,8 @@
 
 template<typename Codebook>
 class SuffixTree {
+    WTF_MAKE_FAST_ALLOCATED;
+    WTF_MAKE_NONCOPYABLE(SuffixTree)
 public:
     SuffixTree(const String& text, unsigned depth)
         : m_depth(depth)
@@ -58,9 +59,10 @@
         Node* current = &m_root;
         int limit = std::min(m_depth, query.length());
         for (int i = 0; i < limit; ++i) {
-            current = current->at(Codebook::codeWord(query[i]));
-            if (!current)
+            auto it = current->find(Codebook::codeWord(query[i]));
+            if (it == current->end())
                 return false;
+            current = it->node;
         }
         return true;
     }
@@ -67,28 +69,40 @@
 
 private:
     class Node {
+        WTF_MAKE_FAST_ALLOCATED;
     public:
         Node(bool isLeaf = false)
-            : m_children(Codebook::codeSize, 0)
-            , m_isLeaf(isLeaf)
+            : m_isLeaf(isLeaf)
         {
         }
 
         ~Node()
         {
-            for (unsigned i = 0; i < m_children.size(); ++i) {
-                Node* child = m_children.at(i);
+            for (auto& entry : m_children) {
+                auto* child = entry.node;
                 if (child && !child->m_isLeaf)
                     delete child;
             }
         }
 
-        Node*& at(int codeWord) { return m_children.at(codeWord); }
+        Node*& childAt(int codeWord);
 
+        auto find(int codeWord)
+        {
+            return std::find_if(m_children.begin(), m_children.end(), [codeWord](auto& entry) {
+                return entry.codeWord == codeWord;
+            });
+        }
+
+        auto end() { return m_children.end(); }
+
     private:
-        typedef Vector<Node*, Codebook::codeSize> ChildrenVector;
+        struct ChildWithCodeWord {
+            int codeWord;
+            Node* node;
+        };
 
-        ChildrenVector m_children;
+        Vector<ChildWithCodeWord> m_children;
         bool m_isLeaf;
     };
 
@@ -99,7 +113,7 @@
             unsigned limit = std::min(base + m_depth, text.length());
             for (unsigned offset = 0; base + offset < limit; ++offset) {
                 ASSERT(current != &m_leaf);
-                Node*& child = current->at(Codebook::codeWord(text[base + offset]));
+                Node*& child = current->childAt(Codebook::codeWord(text[base + offset]));
                 if (!child)
                     child = base + offset + 1 == limit ? &m_leaf : new Node();
                 current = child;
@@ -116,6 +130,14 @@
     Node m_leaf;
 };
 
+template<typename Codebook>
+inline auto SuffixTree<Codebook>::Node::childAt(int codeWord) -> Node*&
+{
+    auto it = find(codeWord);
+    if (it != m_children.end())
+        return it->node;
+    m_children.append(ChildWithCodeWord { codeWord, nullptr });
+    return m_children.last().node;
+}
+
 } // namespace WebCore
-
-#endif // SuffixTree_h
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to