SVGUseElement::findTarget should return nullptr when there is a cycle
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 19 Dec 2018 23:51:03 +0000 (23:51 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 19 Dec 2018 23:51:03 +0000 (23:51 +0000)
https://bugs.webkit.org/show_bug.cgi?id=192840

Reviewed by Tim Horton.

r233366 added an early return to updateShadowTree() when there is a cycle between an use element and its target.
Consolidate this cycle detection code with the one in SVGUseElement::findTarget which detected cycles when
the SVG use element itself had a corresponding element.

No new tests since there should be no behavioral change.

* svg/SVGUseElement.cpp:
(WebCore::SVGUseElement::updateShadowTree):
(WebCore::SVGUseElement::findTarget const):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@239402 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/svg/SVGUseElement.cpp

index 40103de..f0e0538 100644 (file)
@@ -1,3 +1,20 @@
+2018-12-18  Ryosuke Niwa  <rniwa@webkit.org>
+
+        SVGUseElement::findTarget should return nullptr when there is a cycle
+        https://bugs.webkit.org/show_bug.cgi?id=192840
+
+        Reviewed by Tim Horton.
+
+        r233366 added an early return to updateShadowTree() when there is a cycle between an use element and its target.
+        Consolidate this cycle detection code with the one in SVGUseElement::findTarget which detected cycles when
+        the SVG use element itself had a corresponding element.
+
+        No new tests since there should be no behavioral change.
+
+        * svg/SVGUseElement.cpp:
+        (WebCore::SVGUseElement::updateShadowTree):
+        (WebCore::SVGUseElement::findTarget const):
+
 2018-12-19  Myles C. Maxfield  <mmaxfield@apple.com>
 
         [WHLSL] Add a handwritten lexer
index 1fd88c9..bbcc437 100644 (file)
@@ -244,9 +244,7 @@ void SVGUseElement::updateShadowTree()
         return;
     }
 
-    if (isDescendantOf(target))
-        return;
-    
+    RELEASE_ASSERT(!isDescendantOf(target));
     {
         auto& shadowRoot = ensureUserAgentShadowRoot();
         cloneTarget(shadowRoot, *target);
@@ -423,13 +421,16 @@ SVGElement* SVGUseElement::findTarget(String* targetID) const
     if (!target.isConnected() || isDisallowedElement(target))
         return nullptr;
 
-    // Reject any target that has already been cloned to create one of the ancestors of this element,
-    // already in the shadow tree. This is sufficient to prevent cycles.
     if (correspondingElement) {
         for (auto& ancestor : lineageOfType<SVGElement>(*this)) {
             if (ancestor.correspondingElement() == &target)
                 return nullptr;
         }
+    } else {
+        if (target.contains(this))
+            return nullptr;
+        // Target should only refer to a node in the same tree or a node in another document.
+        ASSERT(!isDescendantOrShadowDescendantOf(&target));
     }
 
     return &target;