Title: [109362] trunk
Revision
109362
Author
[email protected]
Date
2012-03-01 10:19:03 -0800 (Thu, 01 Mar 2012)

Log Message

Protect functions using two container node function, each of which can fire mutation events.
https://bugs.webkit.org/show_bug.cgi?id=78397

Reviewed by Ryosuke Niwa.

Source/WebCore:

Tests: fast/dom/document-set-title-mutation-crash.html
       fast/dom/option-text-mutation-crash.html

* dom/Node.cpp:
(WebCore::Node::setTextContent):
* dom/Text.cpp:
(WebCore::Text::replaceWholeText):
* editing/markup.cpp:
(WebCore::trimFragment):
(WebCore::replaceChildrenWithFragment):
(WebCore::replaceChildrenWithText):
* html/HTMLOptionElement.cpp:
(WebCore::HTMLOptionElement::setText):
* html/HTMLScriptElement.cpp:
(WebCore::HTMLScriptElement::setText):
* html/HTMLTableElement.cpp:
(WebCore::HTMLTableElement::insertRow):
* html/HTMLTextAreaElement.cpp:
(WebCore::HTMLTextAreaElement::setDefaultValue):
* html/HTMLTitleElement.cpp:
(WebCore::HTMLTitleElement::setText):

LayoutTests:

* fast/dom/document-set-title-mutation-crash-expected.txt: Added.
* fast/dom/document-set-title-mutation-crash.html: Added.
* fast/dom/option-text-mutation-crash-expected.txt: Added.
* fast/dom/option-text-mutation-crash.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (109361 => 109362)


--- trunk/LayoutTests/ChangeLog	2012-03-01 18:07:59 UTC (rev 109361)
+++ trunk/LayoutTests/ChangeLog	2012-03-01 18:19:03 UTC (rev 109362)
@@ -1,3 +1,15 @@
+2012-03-01  Abhishek Arya  <[email protected]>
+
+        Protect functions using two container node function, each of which can fire mutation events.
+        https://bugs.webkit.org/show_bug.cgi?id=78397
+
+        Reviewed by Ryosuke Niwa.
+
+        * fast/dom/document-set-title-mutation-crash-expected.txt: Added.
+        * fast/dom/document-set-title-mutation-crash.html: Added.
+        * fast/dom/option-text-mutation-crash-expected.txt: Added.
+        * fast/dom/option-text-mutation-crash.html: Added.
+
 2012-03-01  Shinya Kawanaka  <[email protected]>
 
         Appending ShadowRoot into an element should not cause crash.

Added: trunk/LayoutTests/fast/dom/document-set-title-mutation-crash-expected.txt (0 => 109362)


--- trunk/LayoutTests/fast/dom/document-set-title-mutation-crash-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/document-set-title-mutation-crash-expected.txt	2012-03-01 18:19:03 UTC (rev 109362)
@@ -0,0 +1 @@
+PASS

Added: trunk/LayoutTests/fast/dom/document-set-title-mutation-crash.html (0 => 109362)


--- trunk/LayoutTests/fast/dom/document-set-title-mutation-crash.html	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/document-set-title-mutation-crash.html	2012-03-01 18:19:03 UTC (rev 109362)
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<script>
+var count = 0;
+if (!window.layoutTestController)
+    document.write("This test requires GCController.");
+else {
+    layoutTestController.dumpAsText();
+    layoutTestController.waitUntilDone();
+
+    function crash() {
+        if (++count > 1)
+            return;
+        document.open();
+        document.write('PASS');
+        document.close();
+        GCController.collect();
+        setTimeout("layoutTestController.notifyDone()", 0);
+    }
+
+    setTimeout(function () {
+        document.write("<title>");
+        document.title = "First Child";
+        document.getElementsByTagName('title')[0].appendChild(document.createTextNode("Second Child"));
+
+        document.addEventListener('DOMNodeRemovedFromDocument', function () { crash(); }, true);
+        document.title = "New title";
+    }, 0);
+}
+</script>
+</html>
Property changes on: trunk/LayoutTests/fast/dom/document-set-title-mutation-crash.html
___________________________________________________________________

Added: svn:executable

Added: trunk/LayoutTests/fast/dom/option-text-mutation-crash-expected.txt (0 => 109362)


--- trunk/LayoutTests/fast/dom/option-text-mutation-crash-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/option-text-mutation-crash-expected.txt	2012-03-01 18:19:03 UTC (rev 109362)
@@ -0,0 +1 @@
+PASS

Added: trunk/LayoutTests/fast/dom/option-text-mutation-crash.html (0 => 109362)


--- trunk/LayoutTests/fast/dom/option-text-mutation-crash.html	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/option-text-mutation-crash.html	2012-03-01 18:19:03 UTC (rev 109362)
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<script>
+var count = 0;
+if (!window.layoutTestController)
+    document.write("This test requires GCController.");
+else {
+    layoutTestController.dumpAsText();
+    layoutTestController.waitUntilDone();
+
+    function crash() {
+        if (++count > 1)
+            return;
+        document.open();
+        document.write('PASS');
+        document.close();
+        GCController.collect();
+        setTimeout("layoutTestController.notifyDone()", 0);
+    }
+
+    setTimeout(function () {
+        document.write("<select><option>First Child</option></select>");
+        document.getElementsByTagName('option')[0].appendChild(document.createTextNode("Second Child"));
+
+        document.addEventListener('DOMNodeRemovedFromDocument', function () { crash(); }, true);
+        document.getElementsByTagName('option')[0].text = "New text";
+    }, 0);
+}
+</script>
+</html>
Property changes on: trunk/LayoutTests/fast/dom/option-text-mutation-crash.html
___________________________________________________________________

Added: svn:executable

Modified: trunk/Source/WebCore/ChangeLog (109361 => 109362)


--- trunk/Source/WebCore/ChangeLog	2012-03-01 18:07:59 UTC (rev 109361)
+++ trunk/Source/WebCore/ChangeLog	2012-03-01 18:19:03 UTC (rev 109362)
@@ -1,3 +1,32 @@
+2012-03-01  Abhishek Arya  <[email protected]>
+
+        Protect functions using two container node function, each of which can fire mutation events.
+        https://bugs.webkit.org/show_bug.cgi?id=78397
+
+        Reviewed by Ryosuke Niwa.
+
+        Tests: fast/dom/document-set-title-mutation-crash.html
+               fast/dom/option-text-mutation-crash.html
+
+        * dom/Node.cpp:
+        (WebCore::Node::setTextContent):
+        * dom/Text.cpp:
+        (WebCore::Text::replaceWholeText):
+        * editing/markup.cpp:
+        (WebCore::trimFragment):
+        (WebCore::replaceChildrenWithFragment):
+        (WebCore::replaceChildrenWithText):
+        * html/HTMLOptionElement.cpp:
+        (WebCore::HTMLOptionElement::setText):
+        * html/HTMLScriptElement.cpp:
+        (WebCore::HTMLScriptElement::setText):
+        * html/HTMLTableElement.cpp:
+        (WebCore::HTMLTableElement::insertRow):
+        * html/HTMLTextAreaElement.cpp:
+        (WebCore::HTMLTextAreaElement::setDefaultValue):
+        * html/HTMLTitleElement.cpp:
+        (WebCore::HTMLTitleElement::setText):
+
 2012-03-01  Alexey Proskuryakov  <[email protected]>
 
         Some trivial file stream cleanup

Modified: trunk/Source/WebCore/dom/Node.cpp (109361 => 109362)


--- trunk/Source/WebCore/dom/Node.cpp	2012-03-01 18:07:59 UTC (rev 109361)
+++ trunk/Source/WebCore/dom/Node.cpp	2012-03-01 18:19:03 UTC (rev 109362)
@@ -2059,7 +2059,7 @@
         case ENTITY_NODE:
         case ENTITY_REFERENCE_NODE:
         case DOCUMENT_FRAGMENT_NODE: {
-            ContainerNode* container = toContainerNode(this);
+            RefPtr<ContainerNode> container = toContainerNode(this);
 #if ENABLE(MUTATION_OBSERVERS)
             ChildListMutationScope mutation(this);
 #endif

Modified: trunk/Source/WebCore/dom/Text.cpp (109361 => 109362)


--- trunk/Source/WebCore/dom/Text.cpp	2012-03-01 18:07:59 UTC (rev 109361)
+++ trunk/Source/WebCore/dom/Text.cpp	2012-03-01 18:19:03 UTC (rev 109362)
@@ -147,7 +147,7 @@
     RefPtr<Text> endText = const_cast<Text*>(latestLogicallyAdjacentTextNode(this));
 
     RefPtr<Text> protectedThis(this); // Mutation event handlers could cause our last ref to go away
-    ContainerNode* parent = parentNode(); // Protect against mutation handlers moving this node during traversal
+    RefPtr<ContainerNode> parent = parentNode(); // Protect against mutation handlers moving this node during traversal
     ExceptionCode ignored = 0;
     for (RefPtr<Node> n = startText; n && n != this && n->isTextNode() && n->parentNode() == parent;) {
         RefPtr<Node> nodeToRemove(n.release());

Modified: trunk/Source/WebCore/editing/markup.cpp (109361 => 109362)


--- trunk/Source/WebCore/editing/markup.cpp	2012-03-01 18:07:59 UTC (rev 109361)
+++ trunk/Source/WebCore/editing/markup.cpp	2012-03-01 18:19:03 UTC (rev 109362)
@@ -693,7 +693,7 @@
 static void trimFragment(DocumentFragment* fragment, Node* nodeBeforeContext, Node* nodeAfterContext)
 {
     ExceptionCode ec = 0;
-    Node* next;
+    RefPtr<Node> next;
     for (RefPtr<Node> node = fragment->firstChild(); node; node = next) {
         if (nodeBeforeContext->isDescendantOf(node.get())) {
             next = node->traverseNextNode();
@@ -707,9 +707,9 @@
     }
 
     ASSERT(nodeAfterContext->parentNode());
-    for (Node* node = nodeAfterContext; node; node = next) {
+    for (RefPtr<Node> node = nodeAfterContext; node; node = next) {
         next = node->traverseNextSibling();
-        node->parentNode()->removeChild(node, ec);
+        node->parentNode()->removeChild(node.get(), ec);
         ASSERT(!ec);
     }
 }
@@ -1021,10 +1021,12 @@
     return hasOneChild(node) && node->firstChild()->isTextNode();
 }
 
-void replaceChildrenWithFragment(ContainerNode* containerNode, PassRefPtr<DocumentFragment> fragment, ExceptionCode& ec)
+void replaceChildrenWithFragment(ContainerNode* container, PassRefPtr<DocumentFragment> fragment, ExceptionCode& ec)
 {
+    RefPtr<ContainerNode> containerNode(container);
+
 #if ENABLE(MUTATION_OBSERVERS)
-    ChildListMutationScope mutation(containerNode);
+    ChildListMutationScope mutation(containerNode.get());
 #endif
 
     if (!fragment->firstChild()) {
@@ -1032,12 +1034,12 @@
         return;
     }
 
-    if (hasOneTextChild(containerNode) && hasOneTextChild(fragment.get())) {
+    if (hasOneTextChild(containerNode.get()) && hasOneTextChild(fragment.get())) {
         toText(containerNode->firstChild())->setData(toText(fragment->firstChild())->data(), ec);
         return;
     }
 
-    if (hasOneChild(containerNode)) {
+    if (hasOneChild(containerNode.get())) {
         containerNode->replaceChild(fragment, containerNode->firstChild(), ec);
         return;
     }
@@ -1046,20 +1048,22 @@
     containerNode->appendChild(fragment, ec);
 }
 
-void replaceChildrenWithText(ContainerNode* containerNode, const String& text, ExceptionCode& ec)
+void replaceChildrenWithText(ContainerNode* container, const String& text, ExceptionCode& ec)
 {
+    RefPtr<ContainerNode> containerNode(container);
+
 #if ENABLE(MUTATION_OBSERVERS)
-    ChildListMutationScope mutation(containerNode);
+    ChildListMutationScope mutation(containerNode.get());
 #endif
 
-    if (hasOneTextChild(containerNode)) {
+    if (hasOneTextChild(containerNode.get())) {
         toText(containerNode->firstChild())->setData(text, ec);
         return;
     }
 
     RefPtr<Text> textNode = Text::create(containerNode->document(), text);
 
-    if (hasOneChild(containerNode)) {
+    if (hasOneChild(containerNode.get())) {
         containerNode->replaceChild(textNode.release(), containerNode->firstChild(), ec);
         return;
     }

Modified: trunk/Source/WebCore/html/HTMLOptionElement.cpp (109361 => 109362)


--- trunk/Source/WebCore/html/HTMLOptionElement.cpp	2012-03-01 18:07:59 UTC (rev 109361)
+++ trunk/Source/WebCore/html/HTMLOptionElement.cpp	2012-03-01 18:19:03 UTC (rev 109362)
@@ -137,10 +137,12 @@
 
 void HTMLOptionElement::setText(const String &text, ExceptionCode& ec)
 {
+    RefPtr<Node> protectFromMutationEvents(this);
+
     // Changing the text causes a recalc of a select's items, which will reset the selected
     // index to the first item if the select is single selection with a menu list. We attempt to
     // preserve the selected item.
-    HTMLSelectElement* select = ownerSelectElement();
+    RefPtr<HTMLSelectElement> select = ownerSelectElement();
     bool selectIsMenuList = select && select->usesMenuList();
     int oldSelectedIndex = selectIsMenuList ? select->selectedIndex() : -1;
 

Modified: trunk/Source/WebCore/html/HTMLScriptElement.cpp (109361 => 109362)


--- trunk/Source/WebCore/html/HTMLScriptElement.cpp	2012-03-01 18:07:59 UTC (rev 109361)
+++ trunk/Source/WebCore/html/HTMLScriptElement.cpp	2012-03-01 18:19:03 UTC (rev 109362)
@@ -82,6 +82,8 @@
 
 void HTMLScriptElement::setText(const String &value)
 {
+    RefPtr<Node> protectFromMutationEvents(this);
+
     ExceptionCode ec = 0;
     int numChildren = childNodeCount();
 

Modified: trunk/Source/WebCore/html/HTMLTableElement.cpp (109361 => 109362)


--- trunk/Source/WebCore/html/HTMLTableElement.cpp	2012-03-01 18:07:59 UTC (rev 109361)
+++ trunk/Source/WebCore/html/HTMLTableElement.cpp	2012-03-01 18:19:03 UTC (rev 109362)
@@ -187,13 +187,15 @@
         return 0;
     }
 
-    HTMLTableRowElement* lastRow = 0;
-    HTMLTableRowElement* row = 0;
+    RefPtr<Node> protectFromMutationEvents(this);
+
+    RefPtr<HTMLTableRowElement> lastRow = 0;
+    RefPtr<HTMLTableRowElement> row = 0;
     if (index == -1)
         lastRow = HTMLTableRowsCollection::lastRow(this);
     else {
         for (int i = 0; i <= index; ++i) {
-            row = HTMLTableRowsCollection::rowAfter(this, lastRow);
+            row = HTMLTableRowsCollection::rowAfter(this, lastRow.get());
             if (!row) {
                 if (i != index) {
                     ec = INDEX_SIZE_ERR;
@@ -205,7 +207,7 @@
         }
     }
 
-    ContainerNode* parent;
+    RefPtr<ContainerNode> parent;
     if (lastRow)
         parent = row ? row->parentNode() : lastRow->parentNode();
     else {
@@ -220,7 +222,7 @@
     }
 
     RefPtr<HTMLTableRowElement> newRow = HTMLTableRowElement::create(document());
-    parent->insertBefore(newRow, row, ec);
+    parent->insertBefore(newRow, row.get(), ec);
     return newRow.release();
 }
 

Modified: trunk/Source/WebCore/html/HTMLTextAreaElement.cpp (109361 => 109362)


--- trunk/Source/WebCore/html/HTMLTextAreaElement.cpp	2012-03-01 18:07:59 UTC (rev 109361)
+++ trunk/Source/WebCore/html/HTMLTextAreaElement.cpp	2012-03-01 18:19:03 UTC (rev 109362)
@@ -384,8 +384,9 @@
 
 void HTMLTextAreaElement::setDefaultValue(const String& defaultValue)
 {
+    RefPtr<Node> protectFromMutationEvents(this);
+
     // To preserve comments, remove only the text nodes, then add a single text node.
-
     Vector<RefPtr<Node> > textNodes;
     for (Node* n = firstChild(); n; n = n->nextSibling()) {
         if (n->isTextNode())

Modified: trunk/Source/WebCore/html/HTMLTitleElement.cpp (109361 => 109362)


--- trunk/Source/WebCore/html/HTMLTitleElement.cpp	2012-03-01 18:07:59 UTC (rev 109361)
+++ trunk/Source/WebCore/html/HTMLTitleElement.cpp	2012-03-01 18:19:03 UTC (rev 109362)
@@ -88,12 +88,14 @@
 
 void HTMLTitleElement::setText(const String &value)
 {
+    RefPtr<Node> protectFromMutationEvents(this);
+
     ExceptionCode ec = 0;
     int numChildren = childNodeCount();
     
     if (numChildren == 1 && firstChild()->isTextNode())
         toText(firstChild())->setData(value, ec);
-    else {  
+    else {
         // We make a copy here because entity of "value" argument can be Document::m_title,
         // which goes empty during removeChildren() invocation below,
         // which causes HTMLTitleElement::childrenChanged(), which ends up Document::setTitle().
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to