Title: [259152] trunk
Revision
259152
Author
[email protected]
Date
2020-03-27 21:00:36 -0700 (Fri, 27 Mar 2020)

Log Message

Source/WebCore:
Fix null pointer crash in RenderBox::styleDidChange
https://bugs.webkit.org/show_bug.cgi?id=208311

Patch by Eugene But <[email protected]> on 2020-03-27
Reviewed by Ryosuke Niwa.

RenderBox::styleDidChange crashes when changing style for HTMLBodyElement element.
Crash happens on dereferencing null document().documentElement()->renderer() pointer:

if (.... || !documentElementRenderer->style().hasExplicitlySetWritingMode())) {

That HTMLBodyElement was added as the second child of document, which is not allowed per spec:

If parent is a document, and any of the statements below, switched on node,
are true, then throw a "HierarchyRequestError" DOMException:
    .......
    element
        parent has an element child that is not child or a doctype is following child.
    ......
https://dom.spec.whatwg.org/#concept-node-replace

This patch prevents adding HTMLBodyElement as the second child by running more strict checks
inside WebCore::Document::canAcceptChild(). Previously canAcceptChild() would allow all
Replace operations if new child had the same type as old child, even if old child has changed the parent.

If old child has changed the parent (parent is not document), it means that child was removed from document
and it is possible that mutation event handler has already added a new child to document. This is normal
situation, but it means that canAcceptChild() can not short circuit only on comparing the types of old and
new child, and has to run all checks listed in https://dom.spec.whatwg.org/#concept-node-replace

Tests: fast/dom/add-document-child-during-document-child-replacement.html
       fast/dom/add-document-child-and-reparent-old-child-during-document-child-replacement.html

* Source/WebCore/dom/Document.cpp:
(WebCore::Document::canAcceptChild):

LayoutTests:
Test for RenderBox::styleDidChange crash fix
https://bugs.webkit.org/show_bug.cgi?id=208311

Patch by Eugene But <[email protected]> on 2020-03-27
Reviewed by Ryosuke Niwa

add-document-child-during-document-child-replacement.html test adds svg child to a document
from mutation event observer while existing document child is being replaced.
After adding svg child, the document should reject the replacement of existing child, per spec:

If parent is a document, and any of the statements below, switched on node,
are true, then throw a "HierarchyRequestError" DOMException:
    .......
    element
        parent has an element child that is not child or a doctype is following child.
    ......
https://dom.spec.whatwg.org/#concept-node-replace

add-document-child-and-reparent-old-child-during-document-child-replacement.html reparents the old child
to create slightly different state where old child still has a parent but that parent is not document.

* add-document-child-during-document-child-replacement.html:
* add-document-child-and-reparent-old-child-during-document-child-replacement.html:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (259151 => 259152)


--- trunk/LayoutTests/ChangeLog	2020-03-28 03:05:01 UTC (rev 259151)
+++ trunk/LayoutTests/ChangeLog	2020-03-28 04:00:36 UTC (rev 259152)
@@ -1,3 +1,28 @@
+2020-03-27  Eugene But  <[email protected]>
+
+        Test for RenderBox::styleDidChange crash fix
+        https://bugs.webkit.org/show_bug.cgi?id=208311
+
+        Reviewed by Ryosuke Niwa
+
+        add-document-child-during-document-child-replacement.html test adds svg child to a document
+        from mutation event observer while existing document child is being replaced.
+        After adding svg child, the document should reject the replacement of existing child, per spec:
+        
+        If parent is a document, and any of the statements below, switched on node,
+        are true, then throw a "HierarchyRequestError" DOMException:
+            .......
+            element
+                parent has an element child that is not child or a doctype is following child.
+            ......
+        https://dom.spec.whatwg.org/#concept-node-replace
+
+        add-document-child-and-reparent-old-child-during-document-child-replacement.html reparents the old child
+        to create slightly different state where old child still has a parent but that parent is not document.
+ 
+        * add-document-child-during-document-child-replacement.html:
+        * add-document-child-and-reparent-old-child-during-document-child-replacement.html:
+
 2020-03-27  Jason Lawrence  <[email protected]>
 
         [ Mac wk2 ] MediaPlayerPrivateInterface crash in WebKit::VideoFullscreenManager

Added: trunk/LayoutTests/fast/dom/add-document-child-and-reparent-old-child-during-document-child-replacement-expected.txt (0 => 259152)


--- trunk/LayoutTests/fast/dom/add-document-child-and-reparent-old-child-during-document-child-replacement-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/add-document-child-and-reparent-old-child-during-document-child-replacement-expected.txt	2020-03-28 04:00:36 UTC (rev 259152)
@@ -0,0 +1,7 @@
+CONSOLE MESSAGE: line 9: HierarchyRequestError: The operation would yield an incorrect node tree.
+CONSOLE MESSAGE: line 9: HierarchyRequestError: The operation would yield an incorrect node tree.
+CONSOLE MESSAGE: line 9: HierarchyRequestError: The operation would yield an incorrect node tree.
+CONSOLE MESSAGE: line 9: HierarchyRequestError: The operation would yield an incorrect node tree.
+CONSOLE MESSAGE: line 9: HierarchyRequestError: The operation would yield an incorrect node tree.
+PASS document.replaceChild(document.body, document.documentElement) threw exception HierarchyRequestError: The operation would yield an incorrect node tree..
+

Added: trunk/LayoutTests/fast/dom/add-document-child-and-reparent-old-child-during-document-child-replacement.html (0 => 259152)


--- trunk/LayoutTests/fast/dom/add-document-child-and-reparent-old-child-during-document-child-replacement.html	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/add-document-child-and-reparent-old-child-during-document-child-replacement.html	2020-03-28 04:00:36 UTC (rev 259152)
@@ -0,0 +1,14 @@
+<body dir="rtl"></body>
+<script src=""
+<script>
+    let documentDocumentElement = document.documentElement;
+    document.body.offsetHeight;
+    document.addEventListener("DOMSubtreeModified", function() {
+        document.execCommand("SelectAll");
+        let svg = document.createElementNS("http://www.w3.org/2000/svg", "desc");
+        document.appendChild(svg);
+        document.createElement('div').appendChild(documentDocumentElement);
+    });
+
+    shouldThrowErrorName("document.replaceChild(document.body, document.documentElement)", "HierarchyRequestError");
+</script>

Added: trunk/LayoutTests/fast/dom/add-document-child-during-document-child-replacement-expected.txt (0 => 259152)


--- trunk/LayoutTests/fast/dom/add-document-child-during-document-child-replacement-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/add-document-child-during-document-child-replacement-expected.txt	2020-03-28 04:00:36 UTC (rev 259152)
@@ -0,0 +1,7 @@
+CONSOLE MESSAGE: line 8: HierarchyRequestError: The operation would yield an incorrect node tree.
+CONSOLE MESSAGE: line 8: HierarchyRequestError: The operation would yield an incorrect node tree.
+CONSOLE MESSAGE: line 8: HierarchyRequestError: The operation would yield an incorrect node tree.
+CONSOLE MESSAGE: line 8: HierarchyRequestError: The operation would yield an incorrect node tree.
+CONSOLE MESSAGE: line 8: HierarchyRequestError: The operation would yield an incorrect node tree.
+PASS document.replaceChild(document.body, document.documentElement) threw exception HierarchyRequestError: The operation would yield an incorrect node tree..
+

Added: trunk/LayoutTests/fast/dom/add-document-child-during-document-child-replacement.html (0 => 259152)


--- trunk/LayoutTests/fast/dom/add-document-child-during-document-child-replacement.html	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/add-document-child-during-document-child-replacement.html	2020-03-28 04:00:36 UTC (rev 259152)
@@ -0,0 +1,12 @@
+<body dir="rtl"></body>
+<script src=""
+<script>
+    document.body.offsetHeight;
+    document.addEventListener("DOMSubtreeModified", function() {
+        document.execCommand("SelectAll");
+        let svg = document.createElementNS("http://www.w3.org/2000/svg", "desc");
+        document.appendChild(svg);
+    });
+
+    shouldThrowErrorName("document.replaceChild(document.body, document.documentElement)", "HierarchyRequestError");
+</script>

Modified: trunk/Source/WebCore/ChangeLog (259151 => 259152)


--- trunk/Source/WebCore/ChangeLog	2020-03-28 03:05:01 UTC (rev 259151)
+++ trunk/Source/WebCore/ChangeLog	2020-03-28 04:00:36 UTC (rev 259152)
@@ -1,3 +1,40 @@
+2020-03-27  Eugene But  <[email protected]>
+
+        Fix null pointer crash in RenderBox::styleDidChange
+        https://bugs.webkit.org/show_bug.cgi?id=208311
+
+        Reviewed by Ryosuke Niwa.
+
+        RenderBox::styleDidChange crashes when changing style for HTMLBodyElement element.
+        Crash happens on dereferencing null document().documentElement()->renderer() pointer:
+
+        if (.... || !documentElementRenderer->style().hasExplicitlySetWritingMode())) {
+
+        That HTMLBodyElement was added as the second child of document, which is not allowed per spec: 
+        
+        If parent is a document, and any of the statements below, switched on node,
+        are true, then throw a "HierarchyRequestError" DOMException:
+            .......
+            element
+                parent has an element child that is not child or a doctype is following child.
+            ......
+        https://dom.spec.whatwg.org/#concept-node-replace
+
+        This patch prevents adding HTMLBodyElement as the second child by running more strict checks
+        inside WebCore::Document::canAcceptChild(). Previously canAcceptChild() would allow all
+        Replace operations if new child had the same type as old child, even if old child has changed the parent.
+
+        If old child has changed the parent (parent is not document), it means that child was removed from document
+        and it is possible that mutation event handler has already added a new child to document. This is normal
+        situation, but it means that canAcceptChild() can not short circuit only on comparing the types of old and
+        new child, and has to run all checks listed in https://dom.spec.whatwg.org/#concept-node-replace
+       
+        Tests: fast/dom/add-document-child-during-document-child-replacement.html
+               fast/dom/add-document-child-and-reparent-old-child-during-document-child-replacement.html
+
+        * Source/WebCore/dom/Document.cpp:
+        (WebCore::Document::canAcceptChild):
+
 2020-03-27  Wenson Hsieh  <[email protected]>
 
         Web content processes should not be able to arbitrarily request pasteboard data from the UI process

Modified: trunk/Source/WebCore/dom/Document.cpp (259151 => 259152)


--- trunk/Source/WebCore/dom/Document.cpp	2020-03-28 03:05:01 UTC (rev 259151)
+++ trunk/Source/WebCore/dom/Document.cpp	2020-03-28 04:00:36 UTC (rev 259152)
@@ -3879,7 +3879,7 @@
 
 bool Document::canAcceptChild(const Node& newChild, const Node* refChild, AcceptChildOperation operation) const
 {
-    if (operation == AcceptChildOperation::Replace && refChild->nodeType() == newChild.nodeType())
+    if (operation == AcceptChildOperation::Replace && refChild->parentNode() == this && refChild->nodeType() == newChild.nodeType())
         return true;
 
     switch (newChild.nodeType()) {
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to