<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[174452] releases/WebKitGTK/webkit-2.6</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/174452">174452</a></dd>
<dt>Author</dt> <dd>carlosgc@webkit.org</dd>
<dt>Date</dt> <dd>2014-10-08 06:35:15 -0700 (Wed, 08 Oct 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/174137">r174137</a> - 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 &lt;sabouhallawa@apple.com&gt; 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 &lt;sabouhallawa@apple.com&gt; 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.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#releasesWebKitGTKwebkit26LayoutTestsChangeLog">releases/WebKitGTK/webkit-2.6/LayoutTests/ChangeLog</a></li>
<li><a href="#releasesWebKitGTKwebkit26SourceWebCoreChangeLog">releases/WebKitGTK/webkit-2.6/Source/WebCore/ChangeLog</a></li>
<li><a href="#releasesWebKitGTKwebkit26SourceWebCoreplatformgraphicsfiltersFilterEffectcpp">releases/WebKitGTK/webkit-2.6/Source/WebCore/platform/graphics/filters/FilterEffect.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit26SourceWebCoreplatformgraphicsfiltersFilterEffecth">releases/WebKitGTK/webkit-2.6/Source/WebCore/platform/graphics/filters/FilterEffect.h</a></li>
<li><a href="#releasesWebKitGTKwebkit26SourceWebCorerenderingsvgRenderSVGResourceFiltercpp">releases/WebKitGTK/webkit-2.6/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#releasesWebKitGTKwebkit26LayoutTestssvgfilterssvgdeeplynestedcrashexpectedtxt">releases/WebKitGTK/webkit-2.6/LayoutTests/svg/filters/svg-deeply-nested-crash-expected.txt</a></li>
<li><a href="#releasesWebKitGTKwebkit26LayoutTestssvgfilterssvgdeeplynestedcrashhtml">releases/WebKitGTK/webkit-2.6/LayoutTests/svg/filters/svg-deeply-nested-crash.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="releasesWebKitGTKwebkit26LayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.6/LayoutTests/ChangeLog (174451 => 174452)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.6/LayoutTests/ChangeLog        2014-10-08 13:25:09 UTC (rev 174451)
+++ releases/WebKitGTK/webkit-2.6/LayoutTests/ChangeLog        2014-10-08 13:35:15 UTC (rev 174452)
</span><span class="lines">@@ -1,3 +1,19 @@
</span><ins>+2014-09-30  Said Abou-Hallawa  &lt;sabouhallawa@apple.com&gt;
+
+        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.
+
</ins><span class="cx"> 2014-08-01  Sergio Villar Senin  &lt;svillar@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Caret not shown at the end of line in overtype mode
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit26LayoutTestssvgfilterssvgdeeplynestedcrashexpectedtxt"></a>
<div class="addfile"><h4>Added: releases/WebKitGTK/webkit-2.6/LayoutTests/svg/filters/svg-deeply-nested-crash-expected.txt (0 => 174452)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.6/LayoutTests/svg/filters/svg-deeply-nested-crash-expected.txt                                (rev 0)
+++ releases/WebKitGTK/webkit-2.6/LayoutTests/svg/filters/svg-deeply-nested-crash-expected.txt        2014-10-08 13:35:15 UTC (rev 174452)
</span><span class="lines">@@ -0,0 +1 @@
</span><ins>+PASS
</ins></span></pre></div>
<a id="releasesWebKitGTKwebkit26LayoutTestssvgfilterssvgdeeplynestedcrashhtml"></a>
<div class="addfile"><h4>Added: releases/WebKitGTK/webkit-2.6/LayoutTests/svg/filters/svg-deeply-nested-crash.html (0 => 174452)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.6/LayoutTests/svg/filters/svg-deeply-nested-crash.html                                (rev 0)
+++ releases/WebKitGTK/webkit-2.6/LayoutTests/svg/filters/svg-deeply-nested-crash.html        2014-10-08 13:35:15 UTC (rev 174452)
</span><span class="lines">@@ -0,0 +1,50 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;script&gt;
+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 &lt; count; i++) {
+    var feElement = document.createElementNS(&quot;http://www.w3.org/2000/svg&quot;, &quot;feGaussianBlur&quot;);
+        // Make the first effect be the root of the tree
+    if (i == 0) {
+            feElement.setAttribute(&quot;in&quot;, &quot;SourceGraphic&quot;);
+        }
+    feElement.setAttribute(&quot;stdDeviation&quot;, &quot;1.0&quot;);
+    filter.appendChild(feElement);
+  }
+}
+if (window.testRunner)
+    testRunner.dumpAsText();
+window.addEventListener(&quot;load&quot;, function () {
+  // will be ignored: # of effects in the filter map &gt; 200
+  addFilterEffects(&quot;Ignored200&quot;, 100000);
+  // will be ignored: # of effects connected to lastEffect &gt; 100
+  addFilterEffects(&quot;Ignored100&quot;, 50);
+  addFilterEffects(&quot;Ignored100&quot;, 149);
+  // will be used: # of effects in the filter map == 200 but  # of effects connected to lastEffect &lt; 100
+  addFilterEffects(&quot;TripleBlur&quot;, 196);
+  addFilterEffects(&quot;TripleBlur&quot;, 3);
+}, false);
+&lt;/script&gt;
+&lt;svg width=&quot;500&quot; height=&quot;300&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;
+&lt;defs&gt;
+  &lt;filter id=&quot;Ignored200&quot;&gt;
+  &lt;/filter&gt;
+  &lt;filter id=&quot;Ignored100&quot;&gt;
+  &lt;/filter&gt;
+  &lt;filter id=&quot;TripleBlur&quot;&gt;
+  &lt;/filter&gt;
+  &lt;filter id=&quot;ShiftAndBlur&quot;&gt;
+    &lt;feOffset dx=&quot;10&quot; dy=&quot;10&quot; /&gt;
+    &lt;feGaussianBlur stdDeviation=&quot;8.0&quot; /&gt;
+  &lt;/filter&gt;
+&lt;/defs&gt;
+&lt;rect fill=&quot;red&quot; x=&quot;10px&quot; y=&quot;10px&quot; width=&quot;20px&quot; height=&quot;20px&quot; filter=&quot;url(#Ignored200)&quot;/&gt;
+&lt;rect fill=&quot;yellow&quot; x=&quot;10px&quot; y=&quot;10px&quot; width=&quot;20px&quot; height=&quot;20px&quot; filter=&quot;url(#Ignored100)&quot;/&gt;
+&lt;rect fill=&quot;blue&quot; x=&quot;10px&quot; y=&quot;10px&quot; width=&quot;20px&quot; height=&quot;20px&quot; filter=&quot;url(#TripleBlur)&quot;/&gt;
+&lt;circle fill=&quot;green&quot; cx=&quot;100&quot; cy=&quot;100&quot; r=&quot;100&quot;filter=&quot;url(#ShiftAndBlur)&quot; /&gt;
+&lt;text transform=&quot;translate(210,210)&quot;&gt;
+  PASS
+&lt;/text&gt;
+&lt;/svg&gt;
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit26SourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.6/Source/WebCore/ChangeLog (174451 => 174452)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.6/Source/WebCore/ChangeLog        2014-10-08 13:25:09 UTC (rev 174451)
+++ releases/WebKitGTK/webkit-2.6/Source/WebCore/ChangeLog        2014-10-08 13:35:15 UTC (rev 174452)
</span><span class="lines">@@ -1,3 +1,27 @@
</span><ins>+2014-09-30  Said Abou-Hallawa  &lt;sabouhallawa@apple.com&gt;
+
+        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.
+
</ins><span class="cx"> 2014-09-30  David Hyatt  &lt;hyatt@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Remove a multicolumn ASSERT and replace with a guard.
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit26SourceWebCoreplatformgraphicsfiltersFilterEffectcpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.6/Source/WebCore/platform/graphics/filters/FilterEffect.cpp (174451 => 174452)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.6/Source/WebCore/platform/graphics/filters/FilterEffect.cpp        2014-10-08 13:25:09 UTC (rev 174451)
+++ releases/WebKitGTK/webkit-2.6/Source/WebCore/platform/graphics/filters/FilterEffect.cpp        2014-10-08 13:35:15 UTC (rev 174452)
</span><span class="lines">@@ -104,6 +104,23 @@
</span><span class="cx">     return m_inputEffects.at(number).get();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static unsigned collectEffects(const FilterEffect*effect, HashSet&lt;const FilterEffect*&gt;&amp; allEffects)
+{
+    allEffects.add(effect);
+    unsigned size = effect-&gt;numberOfEffectInputs();
+    for (unsigned i = 0; i &lt; size; ++i) {
+        FilterEffect* in = effect-&gt;inputEffect(i);
+        collectEffects(in, allEffects);
+    }
+    return allEffects.size();
+}
+
+unsigned FilterEffect::totalNumberOfEffectInputs() const
+{
+    HashSet&lt;const FilterEffect*&gt; allEffects;
+    return collectEffects(this, allEffects);
+}
+
</ins><span class="cx"> #if ENABLE(OPENCL)
</span><span class="cx"> void FilterEffect::applyAll()
</span><span class="cx"> {
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit26SourceWebCoreplatformgraphicsfiltersFilterEffecth"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.6/Source/WebCore/platform/graphics/filters/FilterEffect.h (174451 => 174452)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.6/Source/WebCore/platform/graphics/filters/FilterEffect.h        2014-10-08 13:25:09 UTC (rev 174451)
+++ releases/WebKitGTK/webkit-2.6/Source/WebCore/platform/graphics/filters/FilterEffect.h        2014-10-08 13:35:15 UTC (rev 174452)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &lt;runtime/Uint8ClampedArray.h&gt;
</span><span class="cx"> 
</span><ins>+#include &lt;wtf/HashSet.h&gt;
</ins><span class="cx"> #include &lt;wtf/RefCounted.h&gt;
</span><span class="cx"> #include &lt;wtf/RefPtr.h&gt;
</span><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><span class="lines">@@ -78,6 +79,7 @@
</span><span class="cx">     FilterEffectVector&amp; inputEffects() { return m_inputEffects; }
</span><span class="cx">     FilterEffect* inputEffect(unsigned) const;
</span><span class="cx">     unsigned numberOfEffectInputs() const { return m_inputEffects.size(); }
</span><ins>+    unsigned totalNumberOfEffectInputs() const;
</ins><span class="cx">     
</span><span class="cx">     inline bool hasResult() const
</span><span class="cx">     {
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit26SourceWebCorerenderingsvgRenderSVGResourceFiltercpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.6/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp (174451 => 174452)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.6/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp        2014-10-08 13:25:09 UTC (rev 174451)
+++ releases/WebKitGTK/webkit-2.6/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp        2014-10-08 13:35:15 UTC (rev 174452)
</span><span class="lines">@@ -76,6 +76,10 @@
</span><span class="cx"> 
</span><span class="cx"> std::unique_ptr&lt;SVGFilterBuilder&gt; RenderSVGResourceFilter::buildPrimitives(SVGFilter* filter) const
</span><span class="cx"> {
</span><ins>+    static const unsigned maxCountChildNodes = 200;
+    if (filterElement().countChildNodes() &gt; maxCountChildNodes)
+        return nullptr;
+
</ins><span class="cx">     FloatRect targetBoundingBox = filter-&gt;targetBoundingBox();
</span><span class="cx"> 
</span><span class="cx">     // Add effects to the builder
</span><span class="lines">@@ -172,8 +176,9 @@
</span><span class="cx">     // Set the scale level in SVGFilter.
</span><span class="cx">     filterData-&gt;filter-&gt;setFilterResolution(scale);
</span><span class="cx"> 
</span><ins>+    static const unsigned maxTotalOfEffectInputs = 100;
</ins><span class="cx">     FilterEffect* lastEffect = filterData-&gt;builder-&gt;lastEffect();
</span><del>-    if (!lastEffect)
</del><ins>+    if (!lastEffect || lastEffect-&gt;totalNumberOfEffectInputs() &gt; maxTotalOfEffectInputs)
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><span class="cx">     RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(lastEffect);
</span></span></pre>
</div>
</div>

</body>
</html>