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().