Title: [182526] releases/WebKitGTK/webkit-2.4
Revision
182526
Author
[email protected]
Date
2015-04-08 00:46:10 -0700 (Wed, 08 Apr 2015)

Log Message

Merge r174137 - Stack overflow with enormous SVG filter
https://bugs.webkit.org/show_bug.cgi?id=63290

Prevent building an SVG filter if it has more than 200 FilterEffect nodes in its map
regardless whether they will be connected to its lastEffect or not. Also discard any
filter which has more 100 contributing FilterEffect nodes in its tree.

Patch by Said Abou-Hallawa <[email protected]> on 2014-09-30
Reviewed by Dean Jackson.

Tests: svg/filters/svg-deeply-nested-crash.html

* platform/graphics/filters/FilterEffect.cpp:
(WebCore::collectEffects):
(WebCore::FilterEffect::totalNumberOfEffectInputs):
* platform/graphics/filters/FilterEffect.h:
-- Add a method to return the total number of input FilterEffect's contributing to a FilterEffect.
* rendering/svg/RenderSVGResourceFilter.cpp:
(WebCore::RenderSVGResourceFilter::buildPrimitives):
-- Do not build a filter if it has more than 200 FilterEffects in its map.
(WebCore::RenderSVGResourceFilter::applyResource):
-- Discard a filter after it was built if it has more than 100 FilterEffects in its tree.

LayoutTests:
Stack overflow with enormous SVG filter.
https://bugs.webkit.org/show_bug.cgi?id=63290.

Patch by Said Abou-Hallawa <[email protected]> on 2014-09-30
Reviewed by Dean Jackson.

Test if an SVG filter with deeply nested tree of FilterEffects can be loaded
with no crash. Make sure other valid filters can still be referenced by SVG
drawing elements. An SVG Filter will be ignored if the number of effects in
its map is greater than 200 or the total number of effects connected to its
last effect is greater than 100.

* svg/filters/svg-deeply-nested-crash-expected.txt: Added.
* svg/filters/svg-deeply-nested-crash.html: Added.

Modified Paths

Added Paths

Diff

Modified: releases/WebKitGTK/webkit-2.4/LayoutTests/ChangeLog (182525 => 182526)


--- releases/WebKitGTK/webkit-2.4/LayoutTests/ChangeLog	2015-04-08 07:44:50 UTC (rev 182525)
+++ releases/WebKitGTK/webkit-2.4/LayoutTests/ChangeLog	2015-04-08 07:46:10 UTC (rev 182526)
@@ -1,3 +1,19 @@
+2014-09-30  Said Abou-Hallawa  <[email protected]>
+
+        Stack overflow with enormous SVG filter.
+        https://bugs.webkit.org/show_bug.cgi?id=63290.
+
+        Reviewed by Dean Jackson.
+
+        Test if an SVG filter with deeply nested tree of FilterEffects can be loaded
+        with no crash. Make sure other valid filters can still be referenced by SVG 
+        drawing elements. An SVG Filter will be ignored if the number of effects in
+        its map is greater than 200 or the total number of effects connected to its 
+        last effect is greater than 100.
+
+        * svg/filters/svg-deeply-nested-crash-expected.txt: Added.
+        * svg/filters/svg-deeply-nested-crash.html: Added.
+
 2015-01-09  Zalan Bujtas  <[email protected]>
 
         Calling clearSelection on a detached RenderObject leads to segfault.

Added: releases/WebKitGTK/webkit-2.4/LayoutTests/svg/filters/svg-deeply-nested-crash-expected.txt (0 => 182526)


--- releases/WebKitGTK/webkit-2.4/LayoutTests/svg/filters/svg-deeply-nested-crash-expected.txt	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.4/LayoutTests/svg/filters/svg-deeply-nested-crash-expected.txt	2015-04-08 07:46:10 UTC (rev 182526)
@@ -0,0 +1 @@
+PASS

Added: releases/WebKitGTK/webkit-2.4/LayoutTests/svg/filters/svg-deeply-nested-crash.html (0 => 182526)


--- releases/WebKitGTK/webkit-2.4/LayoutTests/svg/filters/svg-deeply-nested-crash.html	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.4/LayoutTests/svg/filters/svg-deeply-nested-crash.html	2015-04-08 07:46:10 UTC (rev 182526)
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<script>
+function addFilterEffects(filterId, count) {
+  // inserts a new tree of 'count' feGaussianBlur effects to 
+  // the filter whose id = 'filterId'
+  var filter = document.getElementById(filterId);
+  for (var i = 0; i < count; i++) {
+    var feElement = document.createElementNS("http://www.w3.org/2000/svg", "feGaussianBlur");
+	// Make the first effect be the root of the tree
+    if (i == 0) {
+	    feElement.setAttribute("in", "SourceGraphic");
+	}
+    feElement.setAttribute("stdDeviation", "1.0");
+    filter.appendChild(feElement);
+  }
+}
+if (window.testRunner)
+    testRunner.dumpAsText();
+window.addEventListener("load", function () {
+  // will be ignored: # of effects in the filter map > 200
+  addFilterEffects("Ignored200", 100000);
+  // will be ignored: # of effects connected to lastEffect > 100
+  addFilterEffects("Ignored100", 50);
+  addFilterEffects("Ignored100", 149);
+  // will be used: # of effects in the filter map == 200 but  # of effects connected to lastEffect < 100
+  addFilterEffects("TripleBlur", 196);
+  addFilterEffects("TripleBlur", 3);
+}, false);
+</script>
+<svg width="500" height="300" xmlns="http://www.w3.org/2000/svg">
+<defs>
+  <filter id="Ignored200">
+  </filter>
+  <filter id="Ignored100">
+  </filter>
+  <filter id="TripleBlur">
+  </filter>
+  <filter id="ShiftAndBlur">
+    <feOffset dx="10" dy="10" />
+    <feGaussianBlur stdDeviation="8.0" />
+  </filter>
+</defs>
+<rect fill="red" x="10px" y="10px" width="20px" height="20px" filter="url(#Ignored200)"/>
+<rect fill="yellow" x="10px" y="10px" width="20px" height="20px" filter="url(#Ignored100)"/>
+<rect fill="blue" x="10px" y="10px" width="20px" height="20px" filter="url(#TripleBlur)"/>
+<circle fill="green" cx="100" cy="100" r="100"filter="url(#ShiftAndBlur)" />
+<text transform="translate(210,210)">
+  PASS
+</text>
+</svg>
\ No newline at end of file

Modified: releases/WebKitGTK/webkit-2.4/Source/WebCore/ChangeLog (182525 => 182526)


--- releases/WebKitGTK/webkit-2.4/Source/WebCore/ChangeLog	2015-04-08 07:44:50 UTC (rev 182525)
+++ releases/WebKitGTK/webkit-2.4/Source/WebCore/ChangeLog	2015-04-08 07:46:10 UTC (rev 182526)
@@ -1,3 +1,27 @@
+2014-09-30  Said Abou-Hallawa  <[email protected]>
+
+        Stack overflow with enormous SVG filter
+        https://bugs.webkit.org/show_bug.cgi?id=63290
+
+        Prevent building an SVG filter if it has more than 200 FilterEffect nodes in its map 
+        regardless whether they will be connected to its lastEffect or not. Also discard any
+        filter which has more 100 contributing FilterEffect nodes in its tree.
+
+        Reviewed by Dean Jackson.
+
+        Tests: svg/filters/svg-deeply-nested-crash.html
+
+        * platform/graphics/filters/FilterEffect.cpp:
+        (WebCore::collectEffects):
+        (WebCore::FilterEffect::totalNumberOfEffectInputs):
+        * platform/graphics/filters/FilterEffect.h:
+        -- Add a method to return the total number of input FilterEffect's contributing to a FilterEffect.
+        * rendering/svg/RenderSVGResourceFilter.cpp:
+        (WebCore::RenderSVGResourceFilter::buildPrimitives):
+        -- Do not build a filter if it has more than 200 FilterEffects in its map.
+        (WebCore::RenderSVGResourceFilter::applyResource):
+        -- Discard a filter after it was built if it has more than 100 FilterEffects in its tree.
+
 2014-09-22  Alexey Proskuryakov  <[email protected]>
 
         WebSocket crash when a connection is closed from server side

Modified: releases/WebKitGTK/webkit-2.4/Source/WebCore/platform/graphics/filters/FilterEffect.cpp (182525 => 182526)


--- releases/WebKitGTK/webkit-2.4/Source/WebCore/platform/graphics/filters/FilterEffect.cpp	2015-04-08 07:44:50 UTC (rev 182525)
+++ releases/WebKitGTK/webkit-2.4/Source/WebCore/platform/graphics/filters/FilterEffect.cpp	2015-04-08 07:46:10 UTC (rev 182526)
@@ -99,6 +99,23 @@
     return m_inputEffects.at(number).get();
 }
 
+static unsigned collectEffects(const FilterEffect*effect, HashSet<const FilterEffect*>& allEffects)
+{
+    allEffects.add(effect);
+    unsigned size = effect->numberOfEffectInputs();
+    for (unsigned i = 0; i < size; ++i) {
+        FilterEffect* in = effect->inputEffect(i);
+        collectEffects(in, allEffects);
+    }
+    return allEffects.size();
+}
+
+unsigned FilterEffect::totalNumberOfEffectInputs() const
+{
+    HashSet<const FilterEffect*> allEffects;
+    return collectEffects(this, allEffects);
+}
+
 #if ENABLE(OPENCL)
 void FilterEffect::applyAll()
 {

Modified: releases/WebKitGTK/webkit-2.4/Source/WebCore/platform/graphics/filters/FilterEffect.h (182525 => 182526)


--- releases/WebKitGTK/webkit-2.4/Source/WebCore/platform/graphics/filters/FilterEffect.h	2015-04-08 07:44:50 UTC (rev 182525)
+++ releases/WebKitGTK/webkit-2.4/Source/WebCore/platform/graphics/filters/FilterEffect.h	2015-04-08 07:46:10 UTC (rev 182526)
@@ -29,6 +29,7 @@
 
 #include <runtime/Uint8ClampedArray.h>
 
+#include <wtf/HashSet.h>
 #include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
 #include <wtf/Vector.h>
@@ -77,6 +78,7 @@
     FilterEffectVector& inputEffects() { return m_inputEffects; }
     FilterEffect* inputEffect(unsigned) const;
     unsigned numberOfEffectInputs() const { return m_inputEffects.size(); }
+    unsigned totalNumberOfEffectInputs() const;
     
     inline bool hasResult() const
     {

Modified: releases/WebKitGTK/webkit-2.4/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp (182525 => 182526)


--- releases/WebKitGTK/webkit-2.4/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp	2015-04-08 07:44:50 UTC (rev 182525)
+++ releases/WebKitGTK/webkit-2.4/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp	2015-04-08 07:46:10 UTC (rev 182526)
@@ -78,6 +78,10 @@
 
 std::unique_ptr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(SVGFilter* filter)
 {
+    static const unsigned maxCountChildNodes = 200;
+    if (filterElement().childNodeCount() > maxCountChildNodes)
+        return nullptr;
+
     FloatRect targetBoundingBox = filter->targetBoundingBox();
 
     // Add effects to the builder
@@ -174,8 +178,9 @@
     // Set the scale level in SVGFilter.
     filterData->filter->setFilterResolution(scale);
 
+    static const unsigned maxTotalOfEffectInputs = 100;
     FilterEffect* lastEffect = filterData->builder->lastEffect();
-    if (!lastEffect)
+    if (!lastEffect || lastEffect->totalNumberOfEffectInputs() > maxTotalOfEffectInputs)
         return false;
 
     RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(lastEffect);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to