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);