Title: [104381] trunk
Revision
104381
Author
[email protected]
Date
2012-01-07 01:12:01 -0800 (Sat, 07 Jan 2012)

Log Message

REGRESSION(r104210): Crash inside DynamicSubtreeNodeList::length
https://bugs.webkit.org/show_bug.cgi?id=75731

Reviewed by Andreas Kling.

Source/WebCore: 

The crash was caused by DynamicSubtreeNodeList::SubtreeCaches::domVersionIsConsistent
using m_cachedItem as a way to access the document. Changed SubtreeCaches to use
DynamicSubtreeNodeList's m_node instead.

Test: fast/dom/node-list-length-after-removing-node.html

* dom/DynamicNodeList.cpp:
(WebCore::DynamicSubtreeNodeList::SubtreeCaches::setLengthCache):
(WebCore::DynamicSubtreeNodeList::SubtreeCaches::setItemCache):
(WebCore::DynamicSubtreeNodeList::length):
(WebCore::DynamicSubtreeNodeList::item):
* dom/DynamicNodeList.h:
(WebCore::DynamicSubtreeNodeList::SubtreeCaches::isLengthCacheValid):
(WebCore::DynamicSubtreeNodeList::SubtreeCaches::isItemCacheValid):
(WebCore::DynamicSubtreeNodeList::SubtreeCaches::cachedItem):
(WebCore::DynamicSubtreeNodeList::SubtreeCaches::domVersionIsConsistent):

LayoutTests: 

Add a regression test. It reproduces the crash with a very high probability.

* fast/dom/node-list-length-after-removing-node-expected.txt: Added.
* fast/dom/node-list-length-after-removing-node.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (104380 => 104381)


--- trunk/LayoutTests/ChangeLog	2012-01-07 08:46:38 UTC (rev 104380)
+++ trunk/LayoutTests/ChangeLog	2012-01-07 09:12:01 UTC (rev 104381)
@@ -1,3 +1,15 @@
+2012-01-06  Ryosuke Niwa  <[email protected]>
+
+        REGRESSION(r104210): Crash inside DynamicSubtreeNodeList::length
+        https://bugs.webkit.org/show_bug.cgi?id=75731
+
+        Reviewed by Andreas Kling.
+
+        Add a regression test. It reproduces the crash with a very high probability.
+
+        * fast/dom/node-list-length-after-removing-node-expected.txt: Added.
+        * fast/dom/node-list-length-after-removing-node.html: Added.
+
 2012-01-06  Sheriff Bot  <[email protected]>
 
         Unreviewed, rolling out r104373 and r104374.

Added: trunk/LayoutTests/fast/dom/node-list-length-after-removing-node-expected.txt (0 => 104381)


--- trunk/LayoutTests/fast/dom/node-list-length-after-removing-node-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/node-list-length-after-removing-node-expected.txt	2012-01-07 09:12:01 UTC (rev 104381)
@@ -0,0 +1,3 @@
+This tests accessing an item in node list and then querying the length of the node list after removing the item. WebKit should not crash.
+
+PASS

Added: trunk/LayoutTests/fast/dom/node-list-length-after-removing-node.html (0 => 104381)


--- trunk/LayoutTests/fast/dom/node-list-length-after-removing-node.html	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/node-list-length-after-removing-node.html	2012-01-07 09:12:01 UTC (rev 104381)
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<body _onload_="runTest()">
+<p>This tests accessing an item in node list and then querying the length of the node list after removing the item.
+WebKit should not crash.</p>
+<span></span><span></span>
+<div id="result"></div>
+<script>
+
+var nodeList = document.getElementsByTagName('span');
+document.body.removeChild(nodeList[0]);
+
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+
+if (window.GCController)
+   GCController.collect();
+else {
+    for (var i = 0; i < 10000; ++i)
+        new Object;
+}
+
+document.body.offsetLeft;
+
+function runTest() {
+    document.getElementById('result').innerHTML = nodeList.length == 1 ? 'PASS' : 'FAIL';
+}
+
+</script>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (104380 => 104381)


--- trunk/Source/WebCore/ChangeLog	2012-01-07 08:46:38 UTC (rev 104380)
+++ trunk/Source/WebCore/ChangeLog	2012-01-07 09:12:01 UTC (rev 104381)
@@ -1,3 +1,27 @@
+2012-01-06  Ryosuke Niwa  <[email protected]>
+
+        REGRESSION(r104210): Crash inside DynamicSubtreeNodeList::length
+        https://bugs.webkit.org/show_bug.cgi?id=75731
+
+        Reviewed by Andreas Kling.
+
+        The crash was caused by DynamicSubtreeNodeList::SubtreeCaches::domVersionIsConsistent
+        using m_cachedItem as a way to access the document. Changed SubtreeCaches to use
+        DynamicSubtreeNodeList's m_node instead.
+
+        Test: fast/dom/node-list-length-after-removing-node.html
+
+        * dom/DynamicNodeList.cpp:
+        (WebCore::DynamicSubtreeNodeList::SubtreeCaches::setLengthCache):
+        (WebCore::DynamicSubtreeNodeList::SubtreeCaches::setItemCache):
+        (WebCore::DynamicSubtreeNodeList::length):
+        (WebCore::DynamicSubtreeNodeList::item):
+        * dom/DynamicNodeList.h:
+        (WebCore::DynamicSubtreeNodeList::SubtreeCaches::isLengthCacheValid):
+        (WebCore::DynamicSubtreeNodeList::SubtreeCaches::isItemCacheValid):
+        (WebCore::DynamicSubtreeNodeList::SubtreeCaches::cachedItem):
+        (WebCore::DynamicSubtreeNodeList::SubtreeCaches::domVersionIsConsistent):
+
 2012-01-07  Adam Barth  <[email protected]>
 
         Disconnecting DOMWindow properties is fragile and overly complicated

Modified: trunk/Source/WebCore/dom/DynamicNodeList.cpp (104380 => 104381)


--- trunk/Source/WebCore/dom/DynamicNodeList.cpp	2012-01-07 08:46:38 UTC (rev 104380)
+++ trunk/Source/WebCore/dom/DynamicNodeList.cpp	2012-01-07 09:12:01 UTC (rev 104381)
@@ -36,26 +36,24 @@
 {
 }
 
-void DynamicSubtreeNodeList::SubtreeCaches::setLengthCache(Node* node, unsigned length)
+void DynamicSubtreeNodeList::SubtreeCaches::setLengthCache(Document* document, unsigned length)
 {
-    if (m_isItemCacheValid && !domVersionIsConsistent()) {
-        m_cachedItem = node;
+    if (m_isItemCacheValid && !domVersionIsConsistent(document))
         m_isItemCacheValid = false;
-    } else if (!m_isItemCacheValid)
-        m_cachedItem = node; // Used in domVersionIsConsistent.
     m_cachedLength = length;
     m_isLengthCacheValid = true;
-    m_domTreeVersionAtTimeOfCaching = node->document()->domTreeVersion();
+    m_domTreeVersionAtTimeOfCaching = document->domTreeVersion();
 }
 
 void DynamicSubtreeNodeList::SubtreeCaches::setItemCache(Node* item, unsigned offset)
 {
-    if (m_isLengthCacheValid && !domVersionIsConsistent())
+    Document* document = item->document();
+    if (m_isLengthCacheValid && !domVersionIsConsistent(document))
         m_isLengthCacheValid = false;
     m_cachedItem = item;
     m_cachedItemOffset = offset;
     m_isItemCacheValid = true;
-    m_domTreeVersionAtTimeOfCaching = item->document()->domTreeVersion();
+    m_domTreeVersionAtTimeOfCaching = document->domTreeVersion();
 }
 
 void DynamicSubtreeNodeList::SubtreeCaches::reset()
@@ -78,7 +76,8 @@
 
 unsigned DynamicSubtreeNodeList::length() const
 {
-    if (m_caches.isLengthCacheValid())
+    Document* document = node()->document();
+    if (m_caches.isLengthCacheValid(document))
         return m_caches.cachedLength();
 
     unsigned length = 0;
@@ -86,7 +85,7 @@
     for (Node* n = node()->firstChild(); n; n = n->traverseNextNode(rootNode()))
         length += n->isElementNode() && nodeMatches(static_cast<Element*>(n));
 
-    m_caches.setLengthCache(node(), length);
+    m_caches.setLengthCache(document, length);
 
     return length;
 }
@@ -127,7 +126,7 @@
 {
     int remainingOffset = offset;
     Node* start = node()->firstChild();
-    if (m_caches.isItemCacheValid()) {
+    if (m_caches.isItemCacheValid(node()->document())) {
         if (offset == m_caches.cachedItemOffset())
             return m_caches.cachedItem();
         if (offset > m_caches.cachedItemOffset() || m_caches.cachedItemOffset() - offset < offset) {

Modified: trunk/Source/WebCore/dom/DynamicNodeList.h (104380 => 104381)


--- trunk/Source/WebCore/dom/DynamicNodeList.h	2012-01-07 08:46:38 UTC (rev 104380)
+++ trunk/Source/WebCore/dom/DynamicNodeList.h	2012-01-07 09:12:01 UTC (rev 104381)
@@ -86,14 +86,14 @@
     public:
         SubtreeCaches();
 
-        bool isLengthCacheValid() const { return m_isLengthCacheValid && domVersionIsConsistent(); }
-        bool isItemCacheValid() const { return m_isItemCacheValid && domVersionIsConsistent(); }
+        bool isLengthCacheValid(Document* document) const { return m_isLengthCacheValid && domVersionIsConsistent(document); }
+        bool isItemCacheValid(Document* document) const { return m_isItemCacheValid && domVersionIsConsistent(document); }
 
         unsigned cachedLength() const { return m_cachedLength; }
         Node* cachedItem() const { return m_cachedItem; }
         unsigned cachedItemOffset() const { return m_cachedItemOffset; }
 
-        void setLengthCache(Node* nodeForDocumentVersion, unsigned length);
+        void setLengthCache(Document*, unsigned length);
         void setItemCache(Node*, unsigned offset);
         void reset();
 
@@ -104,9 +104,10 @@
         unsigned m_isLengthCacheValid : 1;
         unsigned m_isItemCacheValid : 1;
 
-        bool domVersionIsConsistent() const
+        bool domVersionIsConsistent(Document* document) const
         {
-            return m_cachedItem && m_cachedItem->document()->domTreeVersion() == m_domTreeVersionAtTimeOfCaching;
+            ASSERT(document);
+            return document->domTreeVersion() == m_domTreeVersionAtTimeOfCaching;
         }
         uint64_t m_domTreeVersionAtTimeOfCaching;
     };
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to