SVG Filters allow invalid elements as children
authorschenney@chromium.org <schenney@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 10 May 2012 15:22:04 +0000 (15:22 +0000)
committerschenney@chromium.org <schenney@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 10 May 2012 15:22:04 +0000 (15:22 +0000)
https://bugs.webkit.org/show_bug.cgi?id=83979

Reviewed by Nikolas Zimmermann.

.:

This test will crash upon load in Chromium, unless the associated fix is in.

* ManualTests/bugzilla-83979.svg: Added.

Source/WebCore:

According to the SVG spec, there are numerous restrictions on the
content of nodes (that is, their children). Specific to this problem,
SVGFilter elements may only contain SVGFilterPrimitive elements, and
those may only contain animation related elements. This patch enforces
the restriction on filters in the render tree, thus preventing us from
having (for instance) content that is inside a filter yet filtered by
the filter.

Manual test: ManualTests/bugzilla-83979.svg

* svg/SVGFilterElement.cpp:
(WebCore::SVGFilterElement::childShouldCreateRenderer): Added to only allow renderers for fe* children
(WebCore):
* svg/SVGFilterElement.h:
(SVGFilterElement):
* svg/SVGFilterPrimitiveStandardAttributes.h: Do not allow any children at all for fe* elements.
(SVGFilterPrimitiveStandardAttributes):

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

ChangeLog
ManualTests/bugzilla-83979.svg [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/svg/SVGFilterElement.cpp
Source/WebCore/svg/SVGFilterElement.h
Source/WebCore/svg/SVGFilterPrimitiveStandardAttributes.h

index 6bab89e..41dcd0d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2012-05-09  Stephen Chenney  <schenney@chromium.org>
+
+        SVG Filters allow invalid elements as children
+        https://bugs.webkit.org/show_bug.cgi?id=83979
+
+        Reviewed by Nikolas Zimmermann.
+
+        This test will crash upon load in Chromium, unless the associated fix is in.
+
+        * ManualTests/bugzilla-83979.svg: Added.
+
 2012-05-09  Kent Tamura  <tkent@chromium.org>
 
         Calendar Picker: Fix a crash by changing input type.
@@ -35,7 +46,7 @@
         https://bugs.webkit.org/show_bug.cgi?id=85907
 
         Reviewed by Rob Buis.
-   
+
         Enable PAGE_POPUP option in make files.
 
         Internal reviewed by Yong Li.
diff --git a/ManualTests/bugzilla-83979.svg b/ManualTests/bugzilla-83979.svg
new file mode 100644 (file)
index 0000000..8712581
--- /dev/null
@@ -0,0 +1,16 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+  <defs>
+    <filter id="ds2">
+      <feGaussianBlur id="blur" result="blur"/>
+    </filter>
+  </defs>
+  <text x="50" y="50">This test passes if it does not crash after load in Debug builds.</text>
+  <image id="image" xlink:href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Crect/%3E%3C/svg%3E" width="50" height="50" filter="url(#ds2)"/>
+<script><![CDATA[
+for (var i = 0; i < 10000; i++) {
+}
+document.getElementById("blur").appendChild(document.getElementById("image").cloneNode());
+for (var i = 0; i < 10000; i++) {
+}
+]]></script>
+</svg>
index d1b3bd2..f2164be 100644 (file)
@@ -1,3 +1,28 @@
+2012-05-10  Stephen Chenney  <schenney@chromium.org>
+
+        SVG Filters allow invalid elements as children
+        https://bugs.webkit.org/show_bug.cgi?id=83979
+
+        Reviewed by Nikolas Zimmermann.
+
+        According to the SVG spec, there are numerous restrictions on the
+        content of nodes (that is, their children). Specific to this problem,
+        SVGFilter elements may only contain SVGFilterPrimitive elements, and
+        those may only contain animation related elements. This patch enforces
+        the restriction on filters in the render tree, thus preventing us from
+        having (for instance) content that is inside a filter yet filtered by
+        the filter.
+
+        Manual test: ManualTests/bugzilla-83979.svg
+
+        * svg/SVGFilterElement.cpp:
+        (WebCore::SVGFilterElement::childShouldCreateRenderer): Added to only allow renderers for fe* children
+        (WebCore):
+        * svg/SVGFilterElement.h:
+        (SVGFilterElement):
+        * svg/SVGFilterPrimitiveStandardAttributes.h: Do not allow any children at all for fe* elements.
+        (SVGFilterPrimitiveStandardAttributes):
+
 2012-05-10  Joe Thomas  <joethomas@motorola.com>
 
         [CSS3 Backgrounds and Borders] Add background-size to the background shorthand
index 9f871c9..2f3e80a 100644 (file)
@@ -27,6 +27,7 @@
 #include "SVGFilterElement.h"
 
 #include "Attr.h"
+#include "NodeRenderingContext.h"
 #include "RenderSVGResourceFilter.h"
 #include "SVGElementInstance.h"
 #include "SVGFilterBuilder.h"
@@ -193,6 +194,45 @@ RenderObject* SVGFilterElement::createRenderer(RenderArena* arena, RenderStyle*)
     return new (arena) RenderSVGResourceFilter(this);
 }
 
+bool SVGFilterElement::childShouldCreateRenderer(const NodeRenderingContext& childContext) const
+{
+    if (!childContext.node()->isSVGElement())
+        return false;
+
+    Element* element = static_cast<Element*>(childContext.node());
+
+    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, allowedChildElementTags, ());
+    if (allowedChildElementTags.isEmpty()) {
+        allowedChildElementTags.add(SVGNames::feBlendTag);
+        allowedChildElementTags.add(SVGNames::feColorMatrixTag);
+        allowedChildElementTags.add(SVGNames::feComponentTransferTag);
+        allowedChildElementTags.add(SVGNames::feCompositeTag);
+        allowedChildElementTags.add(SVGNames::feConvolveMatrixTag);
+        allowedChildElementTags.add(SVGNames::feDiffuseLightingTag);
+        allowedChildElementTags.add(SVGNames::feDisplacementMapTag);
+        allowedChildElementTags.add(SVGNames::feDistantLightTag);
+        allowedChildElementTags.add(SVGNames::feDropShadowTag);
+        allowedChildElementTags.add(SVGNames::feFloodTag);
+        allowedChildElementTags.add(SVGNames::feFuncATag);
+        allowedChildElementTags.add(SVGNames::feFuncBTag);
+        allowedChildElementTags.add(SVGNames::feFuncGTag);
+        allowedChildElementTags.add(SVGNames::feFuncRTag);
+        allowedChildElementTags.add(SVGNames::feGaussianBlurTag);
+        allowedChildElementTags.add(SVGNames::feImageTag);
+        allowedChildElementTags.add(SVGNames::feMergeTag);
+        allowedChildElementTags.add(SVGNames::feMergeNodeTag);
+        allowedChildElementTags.add(SVGNames::feMorphologyTag);
+        allowedChildElementTags.add(SVGNames::feOffsetTag);
+        allowedChildElementTags.add(SVGNames::fePointLightTag);
+        allowedChildElementTags.add(SVGNames::feSpecularLightingTag);
+        allowedChildElementTags.add(SVGNames::feSpotLightTag);
+        allowedChildElementTags.add(SVGNames::feTileTag);
+        allowedChildElementTags.add(SVGNames::feTurbulenceTag);
+    }
+
+    return allowedChildElementTags.contains<QualifiedName, SVGAttributeHashTranslator>(element->tagQName());
+}
+
 bool SVGFilterElement::selfHasRelativeLengths() const
 {
     return x().isRelative()
index e865a51..603c69a 100644 (file)
@@ -55,7 +55,8 @@ private:
     virtual void svgAttributeChanged(const QualifiedName&);
     virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
 
-    virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
+    virtual RenderObject* createRenderer(RenderArena*, RenderStyle*) OVERRIDE;
+    virtual bool childShouldCreateRenderer(const NodeRenderingContext&) const OVERRIDE;
 
     virtual bool selfHasRelativeLengths() const;
 
index 58dc092..f73441d 100644 (file)
@@ -68,8 +68,9 @@ protected:
 private:
     virtual bool isFilterEffect() const { return true; }
 
-    virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
-    virtual bool rendererIsNeeded(const NodeRenderingContext&);
+    virtual RenderObject* createRenderer(RenderArena*, RenderStyle*) OVERRIDE;
+    virtual bool rendererIsNeeded(const NodeRenderingContext&) OVERRIDE;
+    virtual bool childShouldCreateRenderer(const NodeRenderingContext&) const OVERRIDE { return false; }
 
     BEGIN_DECLARE_ANIMATED_PROPERTIES(SVGFilterPrimitiveStandardAttributes)
         DECLARE_ANIMATED_LENGTH(X, x)