Diff
Modified: releases/WebKitGTK/webkit-2.8/LayoutTests/ChangeLog (186407 => 186408)
--- releases/WebKitGTK/webkit-2.8/LayoutTests/ChangeLog 2015-07-07 07:04:52 UTC (rev 186407)
+++ releases/WebKitGTK/webkit-2.8/LayoutTests/ChangeLog 2015-07-07 07:07:02 UTC (rev 186408)
@@ -1,3 +1,23 @@
+2015-06-10 Chris Dumez <[email protected]>
+
+ ASSERT_WITH_SECURITY_IMPLICATION in WebCore::DocumentOrderedMap::getElementById
+ https://bugs.webkit.org/show_bug.cgi?id=145857
+ <rdar://problem/16798440>
+
+ Reviewed by Darin Adler.
+
+ Add layout tests covering different crashes caused by the same bug.
+
+ * fast/dom/script-getElementById-during-insertion-expected.txt: Added.
+ * fast/dom/script-getElementById-during-insertion.html: Added.
+
+ Reduction test case for <rdar://problem/16798440>.
+
+ * fast/dom/script-remove-child-id-map-expected.txt: Added.
+ * fast/dom/script-remove-child-id-map.html: Added.
+
+ Test imported from Blink r178976.
+
2015-06-09 Said Abou-Hallawa <[email protected]>
SVG Fragment is not rendered if it is the css background image of an HTML element
Added: releases/WebKitGTK/webkit-2.8/LayoutTests/fast/dom/script-getElementById-during-insertion-expected.txt (0 => 186408)
--- releases/WebKitGTK/webkit-2.8/LayoutTests/fast/dom/script-getElementById-during-insertion-expected.txt (rev 0)
+++ releases/WebKitGTK/webkit-2.8/LayoutTests/fast/dom/script-getElementById-during-insertion-expected.txt 2015-07-07 07:07:02 UTC (rev 186408)
@@ -0,0 +1,2 @@
+PASS
+
Added: releases/WebKitGTK/webkit-2.8/LayoutTests/fast/dom/script-getElementById-during-insertion.html (0 => 186408)
--- releases/WebKitGTK/webkit-2.8/LayoutTests/fast/dom/script-getElementById-during-insertion.html (rev 0)
+++ releases/WebKitGTK/webkit-2.8/LayoutTests/fast/dom/script-getElementById-during-insertion.html 2015-07-07 07:07:02 UTC (rev 186408)
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+// Tests that we don't crash if a script is being executed as a result of appending a child to it.</p>
+executedScript = false;
+if (window.testRunner)
+ testRunner.dumpAsText();
+</script>
+</head>
+<body>
+<div id="test"></div>
+<script>
+var elem = document.getElementById("test");
+if (!executedScript) {
+ executedScript = true;
+
+ document.documentElement.appendChild(elem.cloneNode(true));
+
+ var range = document.createRange();
+ range.setStartBefore(document.body);
+ range.setEndAfter(document.body);
+ range.surroundContents(document.head.appendChild(document.createElement("script")));
+} else {
+ var span = document.createElement("span");
+ document.documentElement.appendChild(span);
+ span.innerHTML = 'PASS<br/>';
+}
+</script>
+</body>
+</html>
Added: releases/WebKitGTK/webkit-2.8/LayoutTests/fast/dom/script-remove-child-id-map-expected.txt (0 => 186408)
--- releases/WebKitGTK/webkit-2.8/LayoutTests/fast/dom/script-remove-child-id-map-expected.txt (rev 0)
+++ releases/WebKitGTK/webkit-2.8/LayoutTests/fast/dom/script-remove-child-id-map-expected.txt 2015-07-07 07:07:02 UTC (rev 186408)
@@ -0,0 +1,10 @@
+Passes if it doesn't crash and the child is not in the id map
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS document.getElementById('child') is null
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: releases/WebKitGTK/webkit-2.8/LayoutTests/fast/dom/script-remove-child-id-map.html (0 => 186408)
--- releases/WebKitGTK/webkit-2.8/LayoutTests/fast/dom/script-remove-child-id-map.html (rev 0)
+++ releases/WebKitGTK/webkit-2.8/LayoutTests/fast/dom/script-remove-child-id-map.html 2015-07-07 07:07:02 UTC (rev 186408)
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+
+<script src=""
+
+<script>
+description("Passes if it doesn't crash and the child is not in the id map");
+
+var script = document.createElement("script");
+script.type = "dont-execute";
+script.textContent = "script.remove()";
+child = document.createElement("div");
+child.id = "child";
+script.appendChild(child);
+
+// The script won't execute here because the type is invalid, but it also won't
+// get marked as being already run, so changing the children later will run it.
+document.documentElement.appendChild(script);
+
+// Per the spec setting the type has no effect
+script.type = "";
+
+// but changing the children *will* execute the script now that the type is
+// is valid.
+child.remove();
+
+child = null;
+gc();
+
+shouldBeNull("document.getElementById('child')");
+</script>
Modified: releases/WebKitGTK/webkit-2.8/Source/WebCore/ChangeLog (186407 => 186408)
--- releases/WebKitGTK/webkit-2.8/Source/WebCore/ChangeLog 2015-07-07 07:04:52 UTC (rev 186407)
+++ releases/WebKitGTK/webkit-2.8/Source/WebCore/ChangeLog 2015-07-07 07:07:02 UTC (rev 186408)
@@ -1,5 +1,58 @@
2015-06-10 Chris Dumez <[email protected]>
+ ASSERT_WITH_SECURITY_IMPLICATION in WebCore::DocumentOrderedMap::getElementById
+ https://bugs.webkit.org/show_bug.cgi?id=145857
+ <rdar://problem/16798440>
+
+ Reviewed by Darin Adler.
+
+ Make sure Node::insertedInto() gets called on the inserted node and its
+ descendants after its insertion into the tree but *before*
+ ContainerNode::childrenChanged() is called on the parent node. This is
+ needed so that the descendants know they've been inserted into the tree
+ (and their InDocumentFlag flag gets set) before the parent node does
+ anything with them in childrenChanged().
+
+ In the case of <rdar://problem/16798440>, executing HTMLScriptElement's
+ childrenChanged() after appending a child to a script element was causing
+ the script to be executed. The script would call getElementBy() which
+ would traverse the DOM tree and find a matching Element in the newly
+ inserted subtree. However, the matching Element's InDocumentFlag flag was
+ not set yet because the element's insertedInto() method has not been called
+ yet at this point. This would cause us to hit an assertion as
+ DocumentOrderedMap::getElementById() is only supposed to return elements
+ that are in a Document.
+
+ This patch is based on Blink r178976 by <[email protected]>:
+ https://src.chromium.org/viewvc/blink?view=rev&revision=178976
+
+ Tests: fast/dom/script-getElementById-during-insertion.html
+ fast/dom/script-remove-child-id-map.html
+
+ * dom/ContainerNode.cpp:
+ (WebCore::ContainerNode::notifyChildInserted):
+ (WebCore::ContainerNode::notifyChildRemoved):
+ (WebCore::ContainerNode::removeChildren):
+ (WebCore::ContainerNode::parserInsertBefore): Deleted.
+ (WebCore::ContainerNode::removeChild): Deleted.
+ (WebCore::ContainerNode::parserRemoveChild): Deleted.
+ (WebCore::ContainerNode::parserAppendChild): Deleted.
+ (WebCore::ContainerNode::childrenChanged): Deleted.
+ (WebCore::ContainerNode::setAttributeEventListener): Deleted.
+ (WebCore::ContainerNode::querySelector): Deleted.
+ * dom/ContainerNodeAlgorithms.cpp:
+ (WebCore::ChildNodeInsertionNotifier::notifyDescendantInsertedIntoDocument):
+ (WebCore::ChildNodeInsertionNotifier::notifyDescendantInsertedIntoTree):
+ * dom/ContainerNodeAlgorithms.h:
+ (WebCore::ChildNodeInsertionNotifier::notifyNodeInsertedIntoDocument):
+ (WebCore::ChildNodeInsertionNotifier::notifyNodeInsertedIntoTree):
+ (WebCore::ChildNodeInsertionNotifier::notify):
+ (WebCore::ChildNodeRemovalNotifier::notifyNodeRemovedFromDocument): Deleted.
+ * dom/Element.cpp:
+ (WebCore::Element::addShadowRoot):
+
+2015-06-10 Chris Dumez <[email protected]>
+
Drop unused argument for Node::didNotifySubtreeInsertions()
https://bugs.webkit.org/show_bug.cgi?id=145845
Modified: releases/WebKitGTK/webkit-2.8/Source/WebCore/dom/ContainerNode.cpp (186407 => 186408)
--- releases/WebKitGTK/webkit-2.8/Source/WebCore/dom/ContainerNode.cpp 2015-07-07 07:04:52 UTC (rev 186407)
+++ releases/WebKitGTK/webkit-2.8/Source/WebCore/dom/ContainerNode.cpp 2015-07-07 07:07:02 UTC (rev 186408)
@@ -329,6 +329,11 @@
void ContainerNode::notifyChildInserted(Node& child, ChildChangeSource source)
{
+ ChildListMutationScope(*this).childAdded(child);
+
+ NodeVector postInsertionNotificationTargets;
+ ChildNodeInsertionNotifier(*this).notify(child, postInsertionNotificationTargets);
+
ChildChange change;
change.type = child.isElementNode() ? ElementInserted : child.isTextNode() ? TextInserted : NonContentsChildChanged;
change.previousSiblingElement = ElementTraversal::previousSibling(child);
@@ -336,10 +341,15 @@
change.source = source;
childrenChanged(change);
+
+ for (auto& target : postInsertionNotificationTargets)
+ target->didNotifySubtreeInsertions();
}
void ContainerNode::notifyChildRemoved(Node& child, Node* previousSibling, Node* nextSibling, ChildChangeSource source)
{
+ ChildNodeRemovalNotifier(*this).notify(child);
+
ChildChange change;
change.type = is<Element>(child) ? ElementRemoved : is<Text>(child) ? TextRemoved : NonContentsChildChanged;
change.previousSiblingElement = (!previousSibling || is<Element>(*previousSibling)) ? downcast<Element>(previousSibling) : ElementTraversal::previousSibling(*previousSibling);
@@ -369,12 +379,8 @@
newChild->updateAncestorConnectedSubframeCountForInsertion();
- ChildListMutationScope(*this).childAdded(*newChild);
-
notifyChildInserted(*newChild, ChildChangeSourceParser);
- ChildNodeInsertionNotifier(*this).notify(*newChild);
-
newChild->setNeedsStyleRecalc(ReconstructRenderTree);
}
@@ -559,8 +565,6 @@
removeBetween(prev, next, child);
notifyChildRemoved(child, prev, next, ChildChangeSourceAPI);
-
- ChildNodeRemovalNotifier(*this).notify(child);
}
@@ -617,8 +621,6 @@
removeBetween(prev, next, oldChild);
notifyChildRemoved(oldChild, prev, next, ChildChangeSourceParser);
-
- ChildNodeRemovalNotifier(*this).notify(oldChild);
}
// this differs from other remove functions because it forcibly removes all the children,
@@ -642,23 +644,18 @@
// and remove... e.g. stop loading frames, fire unload events.
willRemoveChildren(*this);
- NodeVector removedChildren;
{
WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
{
NoEventDispatchAssertion assertNoEventDispatch;
- removedChildren.reserveInitialCapacity(countChildNodes());
while (RefPtr<Node> n = m_firstChild) {
- removedChildren.append(*m_firstChild);
removeBetween(0, m_firstChild->nextSibling(), *m_firstChild);
+ ChildNodeRemovalNotifier(*this).notify(*n);
}
}
ChildChange change = { AllChildrenRemoved, nullptr, nullptr, ChildChangeSourceAPI };
childrenChanged(change);
-
- for (auto& removedChild : removedChildren)
- ChildNodeRemovalNotifier(*this).notify(removedChild);
}
if (document().svgExtensions()) {
@@ -748,12 +745,8 @@
newChild->updateAncestorConnectedSubframeCountForInsertion();
- ChildListMutationScope(*this).childAdded(*newChild);
-
notifyChildInserted(*newChild, ChildChangeSourceParser);
- ChildNodeInsertionNotifier(*this).notify(*newChild);
-
newChild->setNeedsStyleRecalc(ReconstructRenderTree);
}
@@ -844,12 +837,8 @@
{
ASSERT(child.refCount());
- ChildListMutationScope(*this).childAdded(child);
-
notifyChildInserted(child, ChildChangeSourceAPI);
- ChildNodeInsertionNotifier(*this).notify(child);
-
child.setNeedsStyleRecalc(ReconstructRenderTree);
dispatchChildInsertionEvents(child);
Modified: releases/WebKitGTK/webkit-2.8/Source/WebCore/dom/ContainerNodeAlgorithms.cpp (186407 => 186408)
--- releases/WebKitGTK/webkit-2.8/Source/WebCore/dom/ContainerNodeAlgorithms.cpp 2015-07-07 07:04:52 UTC (rev 186407)
+++ releases/WebKitGTK/webkit-2.8/Source/WebCore/dom/ContainerNodeAlgorithms.cpp 2015-07-07 07:07:02 UTC (rev 186408)
@@ -29,7 +29,7 @@
namespace WebCore {
-void ChildNodeInsertionNotifier::notifyDescendantInsertedIntoDocument(ContainerNode& node)
+void ChildNodeInsertionNotifier::notifyDescendantInsertedIntoDocument(ContainerNode& node, NodeVector& postInsertionNotificationTargets)
{
ChildNodesLazySnapshot snapshot(node);
while (RefPtr<Node> child = snapshot.nextNode()) {
@@ -37,7 +37,7 @@
// we don't want to tell the rest of our children that they've been
// inserted into the document because they haven't.
if (node.inDocument() && child->parentNode() == &node)
- notifyNodeInsertedIntoDocument(*child);
+ notifyNodeInsertedIntoDocument(*child, postInsertionNotificationTargets);
}
if (!is<Element>(node))
@@ -45,19 +45,19 @@
if (RefPtr<ShadowRoot> root = downcast<Element>(node).shadowRoot()) {
if (node.inDocument() && root->hostElement() == &node)
- notifyNodeInsertedIntoDocument(*root);
+ notifyNodeInsertedIntoDocument(*root, postInsertionNotificationTargets);
}
}
-void ChildNodeInsertionNotifier::notifyDescendantInsertedIntoTree(ContainerNode& node)
+void ChildNodeInsertionNotifier::notifyDescendantInsertedIntoTree(ContainerNode& node, NodeVector& postInsertionNotificationTargets)
{
for (Node* child = node.firstChild(); child; child = child->nextSibling()) {
if (is<ContainerNode>(*child))
- notifyNodeInsertedIntoTree(downcast<ContainerNode>(*child));
+ notifyNodeInsertedIntoTree(downcast<ContainerNode>(*child), postInsertionNotificationTargets);
}
if (ShadowRoot* root = node.shadowRoot())
- notifyNodeInsertedIntoTree(*root);
+ notifyNodeInsertedIntoTree(*root, postInsertionNotificationTargets);
}
void ChildNodeRemovalNotifier::notifyDescendantRemovedFromDocument(ContainerNode& node)
Modified: releases/WebKitGTK/webkit-2.8/Source/WebCore/dom/ContainerNodeAlgorithms.h (186407 => 186408)
--- releases/WebKitGTK/webkit-2.8/Source/WebCore/dom/ContainerNodeAlgorithms.h 2015-07-07 07:04:52 UTC (rev 186407)
+++ releases/WebKitGTK/webkit-2.8/Source/WebCore/dom/ContainerNodeAlgorithms.h 2015-07-07 07:07:02 UTC (rev 186408)
@@ -41,16 +41,15 @@
{
}
- void notify(Node&);
+ void notify(Node&, NodeVector& postInsertionNotificationTargets);
private:
- void notifyDescendantInsertedIntoDocument(ContainerNode&);
- void notifyDescendantInsertedIntoTree(ContainerNode&);
- void notifyNodeInsertedIntoDocument(Node&);
- void notifyNodeInsertedIntoTree(ContainerNode&);
+ void notifyDescendantInsertedIntoDocument(ContainerNode&, NodeVector& postInsertionNotificationTargets);
+ void notifyDescendantInsertedIntoTree(ContainerNode&, NodeVector& postInsertionNotificationTargets);
+ void notifyNodeInsertedIntoDocument(Node&, NodeVector& postInsertionNotificationTargets);
+ void notifyNodeInsertedIntoTree(ContainerNode&, NodeVector& postInsertionNotificationTargets);
ContainerNode& m_insertionPoint;
- Vector<Ref<Node>> m_postInsertionNotificationTargets;
};
class ChildNodeRemovalNotifier {
@@ -193,26 +192,26 @@
} // namespace Private
-inline void ChildNodeInsertionNotifier::notifyNodeInsertedIntoDocument(Node& node)
+inline void ChildNodeInsertionNotifier::notifyNodeInsertedIntoDocument(Node& node, NodeVector& postInsertionNotificationTargets)
{
ASSERT(m_insertionPoint.inDocument());
if (Node::InsertionShouldCallDidNotifySubtreeInsertions == node.insertedInto(m_insertionPoint))
- m_postInsertionNotificationTargets.append(node);
+ postInsertionNotificationTargets.append(node);
if (is<ContainerNode>(node))
- notifyDescendantInsertedIntoDocument(downcast<ContainerNode>(node));
+ notifyDescendantInsertedIntoDocument(downcast<ContainerNode>(node), postInsertionNotificationTargets);
}
-inline void ChildNodeInsertionNotifier::notifyNodeInsertedIntoTree(ContainerNode& node)
+inline void ChildNodeInsertionNotifier::notifyNodeInsertedIntoTree(ContainerNode& node, NodeVector& postInsertionNotificationTargets)
{
NoEventDispatchAssertion assertNoEventDispatch;
ASSERT(!m_insertionPoint.inDocument());
if (Node::InsertionShouldCallDidNotifySubtreeInsertions == node.insertedInto(m_insertionPoint))
- m_postInsertionNotificationTargets.append(node);
- notifyDescendantInsertedIntoTree(node);
+ postInsertionNotificationTargets.append(node);
+ notifyDescendantInsertedIntoTree(node, postInsertionNotificationTargets);
}
-inline void ChildNodeInsertionNotifier::notify(Node& node)
+inline void ChildNodeInsertionNotifier::notify(Node& node, NodeVector& postInsertionNotificationTargets)
{
ASSERT_WITH_SECURITY_IMPLICATION(!NoEventDispatchAssertion::isEventDispatchForbidden());
@@ -222,12 +221,9 @@
Ref<Node> protectNode(node);
if (m_insertionPoint.inDocument())
- notifyNodeInsertedIntoDocument(node);
+ notifyNodeInsertedIntoDocument(node, postInsertionNotificationTargets);
else if (is<ContainerNode>(node))
- notifyNodeInsertedIntoTree(downcast<ContainerNode>(node));
-
- for (size_t i = 0; i < m_postInsertionNotificationTargets.size(); ++i)
- m_postInsertionNotificationTargets[i]->didNotifySubtreeInsertions();
+ notifyNodeInsertedIntoTree(downcast<ContainerNode>(node), postInsertionNotificationTargets);
}
Modified: releases/WebKitGTK/webkit-2.8/Source/WebCore/dom/Element.cpp (186407 => 186408)
--- releases/WebKitGTK/webkit-2.8/Source/WebCore/dom/Element.cpp 2015-07-07 07:04:52 UTC (rev 186407)
+++ releases/WebKitGTK/webkit-2.8/Source/WebCore/dom/Element.cpp 2015-07-07 07:07:02 UTC (rev 186408)
@@ -1493,8 +1493,12 @@
shadowRoot.setParentTreeScope(&treeScope());
shadowRoot.distributor().didShadowBoundaryChange(this);
- ChildNodeInsertionNotifier(*this).notify(shadowRoot);
+ NodeVector postInsertionNotificationTargets;
+ ChildNodeInsertionNotifier(*this).notify(shadowRoot, postInsertionNotificationTargets);
+ for (auto& target : postInsertionNotificationTargets)
+ target->didNotifySubtreeInsertions();
+
resetNeedsNodeRenderingTraversalSlowPath();
setNeedsStyleRecalc(ReconstructRenderTree);