Title: [244008] releases/WebKitGTK/webkit-2.24
Revision
244008
Author
carlo...@webkit.org
Date
2019-04-08 05:39:15 -0700 (Mon, 08 Apr 2019)

Log Message

Merge r243175 - Reparenting during a mutation event inside appendChild could result in a circular DOM tree
https://bugs.webkit.org/show_bug.cgi?id=192825

Reviewed by Zalan Bujtas.

Source/WebCore:

The bug was caused by appendChildWithoutPreInsertionValidityCheck, insertBefore and replaceChild
checking the circular dependency against newChild instead of targets even though when newChild
is a document fragment, appendChildWithoutPreInsertionValidityCheck inserts the children of
the document fragment. Fixed the bug by checking the circular dependency against each target child.

Also fixed the bug that checkAcceptChildGuaranteedNodeTypes was not considering shadow inclusive
ancestors or template host elements.

Tests: fast/dom/append-child-with-mutation-event-removal-and-circular-insertion.html
       fast/dom/append-child-with-mutation-event-removal-and-circular-shadow-insertion.html
       fast/dom/append-child-with-mutation-event-removal-and-circular-template-insertion.html
       fast/dom/insert-child-with-mutation-event-removal-and-circular-insertion.html
       fast/dom/insert-child-with-mutation-event-removal-and-circular-shadow-insertion.html
       fast/dom/insert-child-with-mutation-event-removal-and-circular-template-insertion.html
       fast/dom/replace-child-with-mutation-event-removal-and-circular-insertion.html
       fast/dom/replace-child-with-mutation-event-removal-and-circular-shadow-insertion.html
       fast/dom/replace-child-with-mutation-event-removal-and-circular-template-insertion.html

* dom/ContainerNode.cpp:
(WebCore::checkAcceptChildGuaranteedNodeTypes):
(WebCore::ContainerNode::insertBefore):
(WebCore::ContainerNode::replaceChild):
(WebCore::ContainerNode::appendChildWithoutPreInsertionValidityCheck):

LayoutTests:

Added regression tests.

* fast/dom/append-child-with-mutation-event-removal-and-circular-insertion-expected.txt: Added.
* fast/dom/append-child-with-mutation-event-removal-and-circular-insertion.html: Added.
* fast/dom/append-child-with-mutation-event-removal-and-circular-shadow-insertion-expected.txt: Added.
* fast/dom/append-child-with-mutation-event-removal-and-circular-shadow-insertion.html: Added.
* fast/dom/append-child-with-mutation-event-removal-and-circular-template-insertion-expected.txt: Added.
* fast/dom/append-child-with-mutation-event-removal-and-circular-template-insertion.html: Added.
* fast/dom/insert-child-with-mutation-event-removal-and-circular-insertion-expected.txt: Added.
* fast/dom/insert-child-with-mutation-event-removal-and-circular-insertion.html: Added.
* fast/dom/insert-child-with-mutation-event-removal-and-circular-shadow-insertion-expected.txt: Added.
* fast/dom/insert-child-with-mutation-event-removal-and-circular-shadow-insertion.html: Added.
* fast/dom/insert-child-with-mutation-event-removal-and-circular-template-insertion-expected.txt: Added.
* fast/dom/insert-child-with-mutation-event-removal-and-circular-template-insertion.html: Added.
* fast/dom/replace-child-with-mutation-event-removal-and-circular-insertion-expected.txt: Added.
* fast/dom/replace-child-with-mutation-event-removal-and-circular-insertion.html: Added.
* fast/dom/replace-child-with-mutation-event-removal-and-circular-shadow-insertion-expected.txt: Added.
* fast/dom/replace-child-with-mutation-event-removal-and-circular-shadow-insertion.html: Added.
* fast/dom/replace-child-with-mutation-event-removal-and-circular-template-insertion-expected.txt: Added.
* fast/dom/replace-child-with-mutation-event-removal-and-circular-template-insertion.html: Added.

Modified Paths

Added Paths

Diff

Modified: releases/WebKitGTK/webkit-2.24/LayoutTests/ChangeLog (244007 => 244008)


--- releases/WebKitGTK/webkit-2.24/LayoutTests/ChangeLog	2019-04-08 12:39:04 UTC (rev 244007)
+++ releases/WebKitGTK/webkit-2.24/LayoutTests/ChangeLog	2019-04-08 12:39:15 UTC (rev 244008)
@@ -1,3 +1,31 @@
+2019-03-19  Ryosuke Niwa  <rn...@webkit.org>
+
+        Reparenting during a mutation event inside appendChild could result in a circular DOM tree
+        https://bugs.webkit.org/show_bug.cgi?id=192825
+
+        Reviewed by Zalan Bujtas.
+
+        Added regression tests.
+
+        * fast/dom/append-child-with-mutation-event-removal-and-circular-insertion-expected.txt: Added.
+        * fast/dom/append-child-with-mutation-event-removal-and-circular-insertion.html: Added.
+        * fast/dom/append-child-with-mutation-event-removal-and-circular-shadow-insertion-expected.txt: Added.
+        * fast/dom/append-child-with-mutation-event-removal-and-circular-shadow-insertion.html: Added.
+        * fast/dom/append-child-with-mutation-event-removal-and-circular-template-insertion-expected.txt: Added.
+        * fast/dom/append-child-with-mutation-event-removal-and-circular-template-insertion.html: Added.
+        * fast/dom/insert-child-with-mutation-event-removal-and-circular-insertion-expected.txt: Added.
+        * fast/dom/insert-child-with-mutation-event-removal-and-circular-insertion.html: Added.
+        * fast/dom/insert-child-with-mutation-event-removal-and-circular-shadow-insertion-expected.txt: Added.
+        * fast/dom/insert-child-with-mutation-event-removal-and-circular-shadow-insertion.html: Added.
+        * fast/dom/insert-child-with-mutation-event-removal-and-circular-template-insertion-expected.txt: Added.
+        * fast/dom/insert-child-with-mutation-event-removal-and-circular-template-insertion.html: Added.
+        * fast/dom/replace-child-with-mutation-event-removal-and-circular-insertion-expected.txt: Added.
+        * fast/dom/replace-child-with-mutation-event-removal-and-circular-insertion.html: Added.
+        * fast/dom/replace-child-with-mutation-event-removal-and-circular-shadow-insertion-expected.txt: Added.
+        * fast/dom/replace-child-with-mutation-event-removal-and-circular-shadow-insertion.html: Added.
+        * fast/dom/replace-child-with-mutation-event-removal-and-circular-template-insertion-expected.txt: Added.
+        * fast/dom/replace-child-with-mutation-event-removal-and-circular-template-insertion.html: Added.
+
 2019-03-14  Zalan Bujtas  <za...@apple.com>
 
         Cleanup inline boxes when list marker gets blockified

Added: releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/append-child-with-mutation-event-removal-and-circular-insertion-expected.txt (0 => 244008)


--- releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/append-child-with-mutation-event-removal-and-circular-insertion-expected.txt	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/append-child-with-mutation-event-removal-and-circular-insertion-expected.txt	2019-04-08 12:39:15 UTC (rev 244008)
@@ -0,0 +1,13 @@
+This tests re-parenting a child of the document fragment during an insertion so as to create a circular node tree.
+WebKit should detect this case and throw HierarchyRequestError.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS container.appendChild(fragment) threw exception HierarchyRequestError: The operation would yield an incorrect node tree..
+PASS container.parentNode is child
+PASS child.parentNode is null
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/append-child-with-mutation-event-removal-and-circular-insertion.html (0 => 244008)


--- releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/append-child-with-mutation-event-removal-and-circular-insertion.html	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/append-child-with-mutation-event-removal-and-circular-insertion.html	2019-04-08 12:39:15 UTC (rev 244008)
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<script>
+
+description(`This tests re-parenting a child of the document fragment during an insertion so as to create a circular node tree.<br>
+WebKit should detect this case and throw HierarchyRequestError.`);
+
+fragment = document.createDocumentFragment();
+container = document.createElement('div');
+child = fragment.appendChild(document.createElement('div'));
+fragment.addEventListener('DOMSubtreeModified', function() {
+  child.appendChild(container);
+});
+
+shouldThrowErrorName(`container.appendChild(fragment)`, 'HierarchyRequestError');
+shouldBe('container.parentNode', 'child');
+shouldBe('child.parentNode', 'null');
+
+</script>
+</body>
+</html>

Added: releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/append-child-with-mutation-event-removal-and-circular-shadow-insertion-expected.txt (0 => 244008)


--- releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/append-child-with-mutation-event-removal-and-circular-shadow-insertion-expected.txt	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/append-child-with-mutation-event-removal-and-circular-shadow-insertion-expected.txt	2019-04-08 12:39:15 UTC (rev 244008)
@@ -0,0 +1,13 @@
+This tests re-parenting a child of the document fragment during an insertion so as to create a circular node tree.
+WebKit should detect this case and throw HierarchyRequestError.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS container.appendChild(fragment) threw exception HierarchyRequestError: The operation would yield an incorrect node tree..
+PASS container.parentNode is childShadowRoot
+PASS child.parentNode is null
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/append-child-with-mutation-event-removal-and-circular-shadow-insertion.html (0 => 244008)


--- releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/append-child-with-mutation-event-removal-and-circular-shadow-insertion.html	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/append-child-with-mutation-event-removal-and-circular-shadow-insertion.html	2019-04-08 12:39:15 UTC (rev 244008)
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<script>
+
+description(`This tests re-parenting a child of the document fragment during an insertion so as to create a circular node tree.<br>
+WebKit should detect this case and throw HierarchyRequestError.`);
+
+fragment = document.createDocumentFragment();
+container = document.createElement('div');
+child = fragment.appendChild(document.createElement('div'));
+childShadowRoot = child.attachShadow({mode: 'closed'});
+fragment.addEventListener('DOMSubtreeModified', function() {
+    childShadowRoot.appendChild(container);
+});
+
+shouldThrowErrorName(`container.appendChild(fragment)`, 'HierarchyRequestError');
+shouldBe('container.parentNode', 'childShadowRoot');
+shouldBe('child.parentNode', 'null');
+
+</script>
+</body>
+</html>

Added: releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/append-child-with-mutation-event-removal-and-circular-template-insertion-expected.txt (0 => 244008)


--- releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/append-child-with-mutation-event-removal-and-circular-template-insertion-expected.txt	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/append-child-with-mutation-event-removal-and-circular-template-insertion-expected.txt	2019-04-08 12:39:15 UTC (rev 244008)
@@ -0,0 +1,13 @@
+This tests re-parenting a child of the document fragment during an insertion so as to create a circular node tree.
+WebKit should detect this case and throw HierarchyRequestError.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS container.appendChild(fragment) threw exception HierarchyRequestError: The operation would yield an incorrect node tree..
+PASS container.parentNode is child.content
+PASS child.parentNode is null
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/append-child-with-mutation-event-removal-and-circular-template-insertion.html (0 => 244008)


--- releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/append-child-with-mutation-event-removal-and-circular-template-insertion.html	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/append-child-with-mutation-event-removal-and-circular-template-insertion.html	2019-04-08 12:39:15 UTC (rev 244008)
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<script>
+
+description(`This tests re-parenting a child of the document fragment during an insertion so as to create a circular node tree.<br>
+WebKit should detect this case and throw HierarchyRequestError.`);
+
+fragment = document.createDocumentFragment();
+container = document.createElement('div');
+child = fragment.appendChild(document.createElement('template'));
+fragment.addEventListener('DOMSubtreeModified', function() {
+    child.content.appendChild(container);
+});
+
+shouldThrowErrorName(`container.appendChild(fragment)`, 'HierarchyRequestError');
+shouldBe('container.parentNode', 'child.content');
+shouldBe('child.parentNode', 'null');
+
+</script>
+</body>
+</html>

Added: releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/insert-child-with-mutation-event-removal-and-circular-insertion-expected.txt (0 => 244008)


--- releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/insert-child-with-mutation-event-removal-and-circular-insertion-expected.txt	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/insert-child-with-mutation-event-removal-and-circular-insertion-expected.txt	2019-04-08 12:39:15 UTC (rev 244008)
@@ -0,0 +1,13 @@
+This tests re-parenting a child of the document fragment during an insertion so as to create a circular node tree.
+WebKit should detect this case and throw HierarchyRequestError.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS container.insertBefore(fragment, refChild) threw exception HierarchyRequestError: The operation would yield an incorrect node tree..
+PASS container.parentNode is child
+PASS child.parentNode is null
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/insert-child-with-mutation-event-removal-and-circular-insertion.html (0 => 244008)


--- releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/insert-child-with-mutation-event-removal-and-circular-insertion.html	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/insert-child-with-mutation-event-removal-and-circular-insertion.html	2019-04-08 12:39:15 UTC (rev 244008)
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<script>
+
+description(`This tests re-parenting a child of the document fragment during an insertion so as to create a circular node tree.<br>
+WebKit should detect this case and throw HierarchyRequestError.`);
+
+fragment = document.createDocumentFragment();
+container = document.createElement('div');
+refChild = container.appendChild(document.createElement('section'));
+child = fragment.appendChild(document.createElement('div'));
+fragment.addEventListener('DOMSubtreeModified', function() {
+    child.appendChild(container);
+});
+
+shouldThrowErrorName(`container.insertBefore(fragment, refChild)`, 'HierarchyRequestError');
+shouldBe('container.parentNode', 'child');
+shouldBe('child.parentNode', 'null');
+
+</script>
+</body>
+</html>

Added: releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/insert-child-with-mutation-event-removal-and-circular-shadow-insertion-expected.txt (0 => 244008)


--- releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/insert-child-with-mutation-event-removal-and-circular-shadow-insertion-expected.txt	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/insert-child-with-mutation-event-removal-and-circular-shadow-insertion-expected.txt	2019-04-08 12:39:15 UTC (rev 244008)
@@ -0,0 +1,13 @@
+This tests re-parenting a child of the document fragment during an insertion so as to create a circular node tree.
+WebKit should detect this case and throw HierarchyRequestError.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS container.insertBefore(fragment, refChild) threw exception HierarchyRequestError: The operation would yield an incorrect node tree..
+PASS container.parentNode is childShadowRoot
+PASS child.parentNode is null
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/insert-child-with-mutation-event-removal-and-circular-shadow-insertion.html (0 => 244008)


--- releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/insert-child-with-mutation-event-removal-and-circular-shadow-insertion.html	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/insert-child-with-mutation-event-removal-and-circular-shadow-insertion.html	2019-04-08 12:39:15 UTC (rev 244008)
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<script>
+
+description(`This tests re-parenting a child of the document fragment during an insertion so as to create a circular node tree.<br>
+WebKit should detect this case and throw HierarchyRequestError.`);
+
+fragment = document.createDocumentFragment();
+container = document.createElement('div');
+refChild = container.appendChild(document.createElement('section'));
+child = fragment.appendChild(document.createElement('div'));
+childShadowRoot = child.attachShadow({mode: 'closed'});
+fragment.addEventListener('DOMSubtreeModified', function() {
+    childShadowRoot.appendChild(container);
+});
+
+shouldThrowErrorName(`container.insertBefore(fragment, refChild)`, 'HierarchyRequestError');
+shouldBe('container.parentNode', 'childShadowRoot');
+shouldBe('child.parentNode', 'null');
+
+</script>
+</body>
+</html>

Added: releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/insert-child-with-mutation-event-removal-and-circular-template-insertion-expected.txt (0 => 244008)


--- releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/insert-child-with-mutation-event-removal-and-circular-template-insertion-expected.txt	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/insert-child-with-mutation-event-removal-and-circular-template-insertion-expected.txt	2019-04-08 12:39:15 UTC (rev 244008)
@@ -0,0 +1,13 @@
+This tests re-parenting a child of the document fragment during an insertion so as to create a circular node tree.
+WebKit should detect this case and throw HierarchyRequestError.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS container.insertBefore(fragment, refChild) threw exception HierarchyRequestError: The operation would yield an incorrect node tree..
+PASS container.parentNode is child.content
+PASS child.parentNode is null
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/insert-child-with-mutation-event-removal-and-circular-template-insertion.html (0 => 244008)


--- releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/insert-child-with-mutation-event-removal-and-circular-template-insertion.html	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/insert-child-with-mutation-event-removal-and-circular-template-insertion.html	2019-04-08 12:39:15 UTC (rev 244008)
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<script>
+
+description(`This tests re-parenting a child of the document fragment during an insertion so as to create a circular node tree.<br>
+WebKit should detect this case and throw HierarchyRequestError.`);
+
+fragment = document.createDocumentFragment();
+container = document.createElement('div');
+refChild = container.appendChild(document.createElement('section'));
+child = fragment.appendChild(document.createElement('template'));
+fragment.addEventListener('DOMSubtreeModified', function() {
+    child.content.appendChild(container);
+});
+
+shouldThrowErrorName(`container.insertBefore(fragment, refChild)`, 'HierarchyRequestError');
+shouldBe('container.parentNode', 'child.content');
+shouldBe('child.parentNode', 'null');
+
+</script>
+</body>
+</html>

Added: releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/replace-child-with-mutation-event-removal-and-circular-insertion-expected.txt (0 => 244008)


--- releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/replace-child-with-mutation-event-removal-and-circular-insertion-expected.txt	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/replace-child-with-mutation-event-removal-and-circular-insertion-expected.txt	2019-04-08 12:39:15 UTC (rev 244008)
@@ -0,0 +1,13 @@
+This tests re-parenting a child of the document fragment during an insertion so as to create a circular node tree.
+WebKit should detect this case and throw HierarchyRequestError.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS container.replaceChild(fragment, refChild) threw exception HierarchyRequestError: The operation would yield an incorrect node tree..
+PASS container.parentNode is child
+PASS child.parentNode is null
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/replace-child-with-mutation-event-removal-and-circular-insertion.html (0 => 244008)


--- releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/replace-child-with-mutation-event-removal-and-circular-insertion.html	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/replace-child-with-mutation-event-removal-and-circular-insertion.html	2019-04-08 12:39:15 UTC (rev 244008)
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<script>
+
+description(`This tests re-parenting a child of the document fragment during an insertion so as to create a circular node tree.<br>
+WebKit should detect this case and throw HierarchyRequestError.`);
+
+fragment = document.createDocumentFragment();
+container = document.createElement('div');
+refChild = container.appendChild(document.createElement('section'));
+child = fragment.appendChild(document.createElement('div'));
+fragment.addEventListener('DOMSubtreeModified', function() {
+    child.appendChild(container);
+});
+
+shouldThrowErrorName(`container.replaceChild(fragment, refChild)`, 'HierarchyRequestError');
+shouldBe('container.parentNode', 'child');
+shouldBe('child.parentNode', 'null');
+
+</script>
+</body>
+</html>

Added: releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/replace-child-with-mutation-event-removal-and-circular-shadow-insertion-expected.txt (0 => 244008)


--- releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/replace-child-with-mutation-event-removal-and-circular-shadow-insertion-expected.txt	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/replace-child-with-mutation-event-removal-and-circular-shadow-insertion-expected.txt	2019-04-08 12:39:15 UTC (rev 244008)
@@ -0,0 +1,13 @@
+This tests re-parenting a child of the document fragment during an insertion so as to create a circular node tree.
+WebKit should detect this case and throw HierarchyRequestError.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS container.replaceChild(fragment, refChild) threw exception HierarchyRequestError: The operation would yield an incorrect node tree..
+PASS container.parentNode is childShadowRoot
+PASS child.parentNode is null
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/replace-child-with-mutation-event-removal-and-circular-shadow-insertion.html (0 => 244008)


--- releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/replace-child-with-mutation-event-removal-and-circular-shadow-insertion.html	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/replace-child-with-mutation-event-removal-and-circular-shadow-insertion.html	2019-04-08 12:39:15 UTC (rev 244008)
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<script>
+
+description(`This tests re-parenting a child of the document fragment during an insertion so as to create a circular node tree.<br>
+WebKit should detect this case and throw HierarchyRequestError.`);
+
+fragment = document.createDocumentFragment();
+container = document.createElement('div');
+refChild = container.appendChild(document.createElement('section'));
+child = fragment.appendChild(document.createElement('div'));
+childShadowRoot = child.attachShadow({mode: 'closed'});
+fragment.addEventListener('DOMSubtreeModified', function() {
+    childShadowRoot.appendChild(container);
+});
+
+shouldThrowErrorName(`container.replaceChild(fragment, refChild)`, 'HierarchyRequestError');
+shouldBe('container.parentNode', 'childShadowRoot');
+shouldBe('child.parentNode', 'null');
+
+</script>
+</body>
+</html>

Added: releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/replace-child-with-mutation-event-removal-and-circular-template-insertion-expected.txt (0 => 244008)


--- releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/replace-child-with-mutation-event-removal-and-circular-template-insertion-expected.txt	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/replace-child-with-mutation-event-removal-and-circular-template-insertion-expected.txt	2019-04-08 12:39:15 UTC (rev 244008)
@@ -0,0 +1,14 @@
+This tests re-parenting a child of the document fragment during an insertion so as to create a circular node tree.
+WebKit should detect this case and throw HierarchyRequestError.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+FAIL container.replaceChild(fragment, refChild) should throw a HierarchyRequestError. Did not throw.
+PASS container.parentNode is child.content
+FAIL child.parentNode should be null. Was [object HTMLDivElement].
+PASS successfullyParsed is true
+Some tests failed.
+
+TEST COMPLETE
+

Added: releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/replace-child-with-mutation-event-removal-and-circular-template-insertion.html (0 => 244008)


--- releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/replace-child-with-mutation-event-removal-and-circular-template-insertion.html	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.24/LayoutTests/fast/dom/replace-child-with-mutation-event-removal-and-circular-template-insertion.html	2019-04-08 12:39:15 UTC (rev 244008)
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<script>
+
+description(`This tests re-parenting a child of the document fragment during an insertion so as to create a circular node tree.<br>
+WebKit should detect this case and throw HierarchyRequestError.`);
+
+fragment = document.createDocumentFragment();
+container = document.createElement('div');
+refChild = container.appendChild(document.createElement('section'));
+child = fragment.appendChild(document.createElement('template'));
+fragment.addEventListener('DOMSubtreeModified', function() {
+    child.content.appendChild(container);
+});
+
+shouldThrowErrorName(`container.replaceChild(fragment, refChild)`, 'HierarchyRequestError');
+shouldBe('container.parentNode', 'child.content');
+shouldBe('child.parentNode', 'null');
+
+</script>
+</body>
+</html>

Modified: releases/WebKitGTK/webkit-2.24/Source/WebCore/ChangeLog (244007 => 244008)


--- releases/WebKitGTK/webkit-2.24/Source/WebCore/ChangeLog	2019-04-08 12:39:04 UTC (rev 244007)
+++ releases/WebKitGTK/webkit-2.24/Source/WebCore/ChangeLog	2019-04-08 12:39:15 UTC (rev 244008)
@@ -1,3 +1,34 @@
+2019-03-19  Ryosuke Niwa  <rn...@webkit.org>
+
+        Reparenting during a mutation event inside appendChild could result in a circular DOM tree
+        https://bugs.webkit.org/show_bug.cgi?id=192825
+
+        Reviewed by Zalan Bujtas.
+
+        The bug was caused by appendChildWithoutPreInsertionValidityCheck, insertBefore and replaceChild
+        checking the circular dependency against newChild instead of targets even though when newChild
+        is a document fragment, appendChildWithoutPreInsertionValidityCheck inserts the children of
+        the document fragment. Fixed the bug by checking the circular dependency against each target child.
+
+        Also fixed the bug that checkAcceptChildGuaranteedNodeTypes was not considering shadow inclusive
+        ancestors or template host elements.
+
+        Tests: fast/dom/append-child-with-mutation-event-removal-and-circular-insertion.html
+               fast/dom/append-child-with-mutation-event-removal-and-circular-shadow-insertion.html
+               fast/dom/append-child-with-mutation-event-removal-and-circular-template-insertion.html
+               fast/dom/insert-child-with-mutation-event-removal-and-circular-insertion.html
+               fast/dom/insert-child-with-mutation-event-removal-and-circular-shadow-insertion.html
+               fast/dom/insert-child-with-mutation-event-removal-and-circular-template-insertion.html
+               fast/dom/replace-child-with-mutation-event-removal-and-circular-insertion.html
+               fast/dom/replace-child-with-mutation-event-removal-and-circular-shadow-insertion.html
+               fast/dom/replace-child-with-mutation-event-removal-and-circular-template-insertion.html
+
+        * dom/ContainerNode.cpp:
+        (WebCore::checkAcceptChildGuaranteedNodeTypes):
+        (WebCore::ContainerNode::insertBefore):
+        (WebCore::ContainerNode::replaceChild):
+        (WebCore::ContainerNode::appendChildWithoutPreInsertionValidityCheck):
+
 2019-03-14  Ryosuke Niwa  <rn...@webkit.org>
 
         Storing a Node in Ref/RefPtr inside its destructor results in double delete

Modified: releases/WebKitGTK/webkit-2.24/Source/WebCore/dom/ContainerNode.cpp (244007 => 244008)


--- releases/WebKitGTK/webkit-2.24/Source/WebCore/dom/ContainerNode.cpp	2019-04-08 12:39:04 UTC (rev 244007)
+++ releases/WebKitGTK/webkit-2.24/Source/WebCore/dom/ContainerNode.cpp	2019-04-08 12:39:15 UTC (rev 244008)
@@ -342,7 +342,7 @@
 {
     ASSERT(!newParent.isDocumentTypeNode());
     ASSERT(isChildTypeAllowed(newParent, newChild));
-    if (newChild.contains(&newParent))
+    if (containsConsideringHostElements(newChild, newParent))
         return Exception { HierarchyRequestError };
     return { };
 }
@@ -388,9 +388,11 @@
         return { };
 
     // We need this extra check because collectChildrenAndRemoveFromOldParent() can fire mutation events.
-    auto checkAcceptResult = checkAcceptChildGuaranteedNodeTypes(*this, newChild);
-    if (checkAcceptResult.hasException())
-        return checkAcceptResult.releaseException();
+    for (auto& child : targets) {
+        auto checkAcceptResult = checkAcceptChildGuaranteedNodeTypes(*this, child);
+        if (checkAcceptResult.hasException())
+            return checkAcceptResult.releaseException();
+    }
 
     InspectorInstrumentation::willInsertDOMNode(document(), *this);
 
@@ -504,9 +506,11 @@
     }
 
     // Do this one more time because collectChildrenAndRemoveFromOldParent() fires a MutationEvent.
-    validityResult = checkPreReplacementValidity(*this, newChild, oldChild);
-    if (validityResult.hasException())
-        return validityResult.releaseException();
+    for (auto& child : targets) {
+        validityResult = checkPreReplacementValidity(*this, child, oldChild);
+        if (validityResult.hasException())
+            return validityResult.releaseException();
+    }
 
     // Remove the node we're replacing.
     Ref<Node> protectOldChild(oldChild);
@@ -520,9 +524,11 @@
             return removeResult.releaseException();
 
         // Does this one more time because removeChild() fires a MutationEvent.
-        validityResult = checkPreReplacementValidity(*this, newChild, oldChild);
-        if (validityResult.hasException())
-            return validityResult.releaseException();
+        for (auto& child : targets) {
+            validityResult = checkPreReplacementValidity(*this, child, oldChild);
+            if (validityResult.hasException())
+                return validityResult.releaseException();
+        }
     }
 
     InspectorInstrumentation::willInsertDOMNode(document(), *this);
@@ -699,9 +705,11 @@
         return { };
 
     // We need this extra check because collectChildrenAndRemoveFromOldParent() can fire mutation events.
-    auto nodeTypeResult = checkAcceptChildGuaranteedNodeTypes(*this, newChild);
-    if (nodeTypeResult.hasException())
-        return nodeTypeResult.releaseException();
+    for (auto& child : targets) {
+        auto nodeTypeResult = checkAcceptChildGuaranteedNodeTypes(*this, child);
+        if (nodeTypeResult.hasException())
+            return nodeTypeResult.releaseException();
+    }
 
     InspectorInstrumentation::willInsertDOMNode(document(), *this);
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to