<!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>[191731] trunk</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/191731">191731</a></dd>
<dt>Author</dt> <dd>said@apple.com</dd>
<dt>Date</dt> <dd>2015-10-29 10:12:43 -0700 (Thu, 29 Oct 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>Exploitable crash happens when an SVG contains an indirect resource inheritance cycle
https://bugs.webkit.org/show_bug.cgi?id=150203
Reviewed by Brent Fulgham.
Source/WebCore:
Detecting cycles in SVG resource references happens in two places.
1. In SVGResourcesCycleSolver::resolveCycles() which it is called from
SVGResourcesCache::addResourcesFromRenderer(). When a cycle is deleted,
SVGResourcesCycleSolver::breakCycle() is called to break the link. In
the case of a cyclic resource inheritance, SVGResources::resetLinkedResource()
is called to break this cycle.
2. SVGPatternElement::collectPatternAttributes() which is called from
RenderSVGResourcePattern::buildPattern(). The purpose is to resolve
the pattern attributes and to build a tile image which can be used to
fill the SVG element renderer. Detecting the cyclic resource reference
in this function is not sufficient and can detect simple cycles like
<pattern id="a" xlink:href="#b"/>
<pattern id="b" xlink:href="#a"/>.
But it does not detect cycles like:
<pattern id="a">
<rect fill="url(#b)"/>
</pattern>
<pattern id="b" xlink:href="#a"/>.
The fix is to get rid of SVGPatternElement::collectPatternAttributes() which
uses SVGURIReference::targetElementFromIRIString() to navigates through the
referenced resource elements and tries to detect cycles. Instead we can
implement RenderSVGResourcePattern::collectPatternAttributes() which calls
SVGResourcesCache::cachedResourcesForRenderer() to get the SVGResources
of the pattern. Then we use SVGResources::linkedResource() to navigate the
resource inheritance tree. The cached SVGResources is guaranteed to be free
of cycles.
Tests: svg/custom/pattern-content-inheritance-cycle.svg
* rendering/svg/RenderSVGResourcePattern.cpp:
(WebCore::RenderSVGResourcePattern::collectPatternAttributes):
Collect the pattern attributes through the cachedResourcesForRenderer().
(WebCore::RenderSVGResourcePattern::buildPattern):
Direct the call to the renderer function.
* rendering/svg/RenderSVGResourcePattern.h:
* rendering/svg/RenderSVGRoot.cpp:
(WebCore::RenderSVGRoot::layout):
RenderSVGRoot needs to call SVGResourcesCache::clientStyleChanged() for all
the invalidated resources. If an attribute of an SVG resource was updated
dynamically, the cached SVGResources associated with the renderer of this
resource was stale.
* rendering/svg/SVGRenderTreeAsText.cpp:
(WebCore::writeSVGResourceContainer):
Direct the call to the renderer function.
* svg/SVGPatternElement.cpp:
(WebCore::SVGPatternElement::collectPatternAttributes):
(WebCore::setPatternAttributes): Deleted.
collectPatternAttributes() is a replacement of setPatternAttributes().
LayoutTests:
Ensure that we do not crash when an SVG has an indirect cyclic resource
inheritance. Make sure the cyclic resource was just ignored as if it did
not exist.
* svg/custom/pattern-content-inheritance-cycle-expected.svg: Added.
* svg/custom/pattern-content-inheritance-cycle.svg: Added.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorerenderingsvgRenderSVGResourcePatterncpp">trunk/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingsvgRenderSVGResourcePatternh">trunk/Source/WebCore/rendering/svg/RenderSVGResourcePattern.h</a></li>
<li><a href="#trunkSourceWebCorerenderingsvgRenderSVGRootcpp">trunk/Source/WebCore/rendering/svg/RenderSVGRoot.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingsvgSVGRenderTreeAsTextcpp">trunk/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp</a></li>
<li><a href="#trunkSourceWebCoresvgSVGPatternElementcpp">trunk/Source/WebCore/svg/SVGPatternElement.cpp</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestssvgcustompatterncontentinheritancecycleexpectedsvg">trunk/LayoutTests/svg/custom/pattern-content-inheritance-cycle-expected.svg</a></li>
<li><a href="#trunkLayoutTestssvgcustompatterncontentinheritancecyclesvg">trunk/LayoutTests/svg/custom/pattern-content-inheritance-cycle.svg</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (191730 => 191731)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-10-29 16:51:41 UTC (rev 191730)
+++ trunk/LayoutTests/ChangeLog        2015-10-29 17:12:43 UTC (rev 191731)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2015-10-29 Said Abou-Hallawa <sabouhallawa@apple.com>
+
+ Exploitable crash happens when an SVG contains an indirect resource inheritance cycle
+ https://bugs.webkit.org/show_bug.cgi?id=150203
+
+ Reviewed by Brent Fulgham.
+
+ Ensure that we do not crash when an SVG has an indirect cyclic resource
+ inheritance. Make sure the cyclic resource was just ignored as if it did
+ not exist.
+
+ * svg/custom/pattern-content-inheritance-cycle-expected.svg: Added.
+ * svg/custom/pattern-content-inheritance-cycle.svg: Added.
+
</ins><span class="cx"> 2015-10-29 Carlos Garcia Campos <cgarcia@igalia.com>
</span><span class="cx">
</span><span class="cx"> Unreviewed. GTK+ gardening: rebaseline more tests after r191623.
</span></span></pre></div>
<a id="trunkLayoutTestssvgcustompatterncontentinheritancecycleexpectedsvg"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/svg/custom/pattern-content-inheritance-cycle-expected.svg (0 => 191731)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/svg/custom/pattern-content-inheritance-cycle-expected.svg         (rev 0)
+++ trunk/LayoutTests/svg/custom/pattern-content-inheritance-cycle-expected.svg        2015-10-29 17:12:43 UTC (rev 191731)
</span><span class="lines">@@ -0,0 +1,16 @@
</span><ins>+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <g fill="none" stroke="black" stroke-width="1">
+ <circle cx="75" cy="75" fill="lime" r="50"/>
+ <circle cx="200" cy="75" fill="none" r="50"/>
+
+ <circle cx="75" cy="200" fill="lime" r="50"/>
+ <circle cx="200" cy="200" fill="none" r="50"/>
+ <circle cx="325" cy="200" fill="none" r="50"/>
+
+ <circle cx="75" cy="325" fill="lime" r="50"/>
+ <circle cx="200" cy="325" fill="none" r="50"/>
+
+ <circle cx="75" cy="450" fill="lime" r="50"/>
+ <circle cx="200" cy="450" fill="none" r="50"/>
+ </g>
+</svg>
</ins></span></pre></div>
<a id="trunkLayoutTestssvgcustompatterncontentinheritancecyclesvg"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/svg/custom/pattern-content-inheritance-cycle.svg (0 => 191731)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/svg/custom/pattern-content-inheritance-cycle.svg         (rev 0)
+++ trunk/LayoutTests/svg/custom/pattern-content-inheritance-cycle.svg        2015-10-29 17:12:43 UTC (rev 191731)
</span><span class="lines">@@ -0,0 +1,56 @@
</span><ins>+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <!-- a => b => a -->
+ <pattern id="a" x="0" y="0" width=".25" height=".25">
+ <rect fill="lime" width="100%" height="100%"/>
+ <rect fill="url(#b)" width="100%" height="100%"/>
+ </pattern>
+ <pattern id="b" xlink:href="#a"/>
+
+ <!-- l => m => n => l -->
+ <pattern id="l" x="0" y="0" width=".25" height=".25">
+ <rect fill="lime" width="100%" height="100%"/>
+ <rect fill="url(#m)" width="100%" height="100%"/>
+ </pattern>
+ <pattern id="m" xlink:href="#n"/>
+ <pattern id="n" xlink:href="#l"/>
+
+ <!-- p => q -->
+ <pattern id="p" x="0" y="0" width=".25" height=".25">
+ <rect fill="lime" width="100%" height="100%"/>
+ <rect fill="url(#q)" width="100%" height="100%"/>
+ </pattern>
+ <pattern id="q"/>
+
+ <!-- t => s -->
+ <pattern id="s" x="0" y="0" width=".25" height=".25">
+ <rect fill="lime" width="100%" height="100%"/>
+ <rect id="r" width="100%" height="100%"/>
+ </pattern>
+ <pattern id="t" xlink:href="#s"/>
+ </defs>
+ <g fill="none" stroke="black" stroke-width="1">
+ <circle cx="75" cy="75" fill="url(#a)" r="50"/>
+ <circle cx="200" cy="75" fill="url(#b)" r="50"/>
+
+ <circle cx="75" cy="200" fill="url(#l)" r="50"/>
+ <circle cx="200" cy="200" fill="url(#m)" r="50"/>
+ <circle cx="325" cy="200" fill="url(#n)" r="50"/>
+
+ <circle cx="75" cy="325" fill="url(#p)" r="50"/>
+ <circle cx="200" cy="325" fill="url(#q)" r="50"/>
+
+ <circle cx="75" cy="450" fill="url(#s)" r="50"/>
+ <circle cx="200" cy="450" fill="url(#t)" r="50"/>
+ </g>
+ <script>
+ // Add q => p to get p => q => p
+ document.getElementById("q").setAttributeNS("http://www.w3.org/1999/xlink", "href", "#p");
+
+ // Add s => t to get s => t => s
+ document.getElementById("r").setAttribute("fill", "url(#t)");
+
+ // Force layout
+ document.documentElement.removeAttribute("class");
+ </script>
+</svg>
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (191730 => 191731)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-10-29 16:51:41 UTC (rev 191730)
+++ trunk/Source/WebCore/ChangeLog        2015-10-29 17:12:43 UTC (rev 191731)
</span><span class="lines">@@ -1,3 +1,65 @@
</span><ins>+2015-10-29 Said Abou-Hallawa <sabouhallawa@apple.com>
+
+ Exploitable crash happens when an SVG contains an indirect resource inheritance cycle
+ https://bugs.webkit.org/show_bug.cgi?id=150203
+
+ Reviewed by Brent Fulgham.
+
+ Detecting cycles in SVG resource references happens in two places.
+ 1. In SVGResourcesCycleSolver::resolveCycles() which it is called from
+ SVGResourcesCache::addResourcesFromRenderer(). When a cycle is deleted,
+ SVGResourcesCycleSolver::breakCycle() is called to break the link. In
+ the case of a cyclic resource inheritance, SVGResources::resetLinkedResource()
+ is called to break this cycle.
+ 2. SVGPatternElement::collectPatternAttributes() which is called from
+ RenderSVGResourcePattern::buildPattern(). The purpose is to resolve
+ the pattern attributes and to build a tile image which can be used to
+ fill the SVG element renderer. Detecting the cyclic resource reference
+ in this function is not sufficient and can detect simple cycles like
+ <pattern id="a" xlink:href="#b"/>
+ <pattern id="b" xlink:href="#a"/>.
+ But it does not detect cycles like:
+ <pattern id="a">
+ <rect fill="url(#b)"/>
+ </pattern>
+ <pattern id="b" xlink:href="#a"/>.
+
+ The fix is to get rid of SVGPatternElement::collectPatternAttributes() which
+ uses SVGURIReference::targetElementFromIRIString() to navigates through the
+ referenced resource elements and tries to detect cycles. Instead we can
+ implement RenderSVGResourcePattern::collectPatternAttributes() which calls
+ SVGResourcesCache::cachedResourcesForRenderer() to get the SVGResources
+ of the pattern. Then we use SVGResources::linkedResource() to navigate the
+ resource inheritance tree. The cached SVGResources is guaranteed to be free
+ of cycles.
+
+ Tests: svg/custom/pattern-content-inheritance-cycle.svg
+
+ * rendering/svg/RenderSVGResourcePattern.cpp:
+ (WebCore::RenderSVGResourcePattern::collectPatternAttributes):
+ Collect the pattern attributes through the cachedResourcesForRenderer().
+
+ (WebCore::RenderSVGResourcePattern::buildPattern):
+ Direct the call to the renderer function.
+
+ * rendering/svg/RenderSVGResourcePattern.h:
+
+ * rendering/svg/RenderSVGRoot.cpp:
+ (WebCore::RenderSVGRoot::layout):
+ RenderSVGRoot needs to call SVGResourcesCache::clientStyleChanged() for all
+ the invalidated resources. If an attribute of an SVG resource was updated
+ dynamically, the cached SVGResources associated with the renderer of this
+ resource was stale.
+
+ * rendering/svg/SVGRenderTreeAsText.cpp:
+ (WebCore::writeSVGResourceContainer):
+ Direct the call to the renderer function.
+
+ * svg/SVGPatternElement.cpp:
+ (WebCore::SVGPatternElement::collectPatternAttributes):
+ (WebCore::setPatternAttributes): Deleted.
+ collectPatternAttributes() is a replacement of setPatternAttributes().
+
</ins><span class="cx"> 2015-10-29 Xabier Rodriguez Calvar <calvaris@igalia.com>
</span><span class="cx">
</span><span class="cx"> [Streams API] Turn WS states into integers and fix state initialization
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingsvgRenderSVGResourcePatterncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp (191730 => 191731)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp        2015-10-29 16:51:41 UTC (rev 191730)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp        2015-10-29 17:12:43 UTC (rev 191731)
</span><span class="lines">@@ -54,6 +54,19 @@
</span><span class="cx"> markClientForInvalidation(client, markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void RenderSVGResourcePattern::collectPatternAttributes(PatternAttributes& attributes) const
+{
+ const RenderSVGResourcePattern* current = this;
+
+ while (current) {
+ const SVGPatternElement& pattern = current->patternElement();
+ pattern.collectPatternAttributes(attributes);
+
+ auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*current);
+ current = resources ? downcast<RenderSVGResourcePattern>(resources->linkedResource()) : nullptr;
+ }
+}
+
</ins><span class="cx"> PatternData* RenderSVGResourcePattern::buildPattern(RenderElement& renderer, unsigned short resourceMode, GraphicsContext& context)
</span><span class="cx"> {
</span><span class="cx"> PatternData* currentData = m_patternMap.get(&renderer);
</span><span class="lines">@@ -64,7 +77,7 @@
</span><span class="cx"> patternElement().synchronizeAnimatedSVGAttribute(anyQName());
</span><span class="cx">
</span><span class="cx"> m_attributes = PatternAttributes();
</span><del>- patternElement().collectPatternAttributes(m_attributes);
</del><ins>+ collectPatternAttributes(m_attributes);
</ins><span class="cx"> m_shouldCollectPatternAttributes = false;
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingsvgRenderSVGResourcePatternh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResourcePattern.h (191730 => 191731)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/svg/RenderSVGResourcePattern.h        2015-10-29 16:51:41 UTC (rev 191730)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResourcePattern.h        2015-10-29 17:12:43 UTC (rev 191731)
</span><span class="lines">@@ -53,6 +53,8 @@
</span><span class="cx">
</span><span class="cx"> virtual RenderSVGResourceType resourceType() const override { return PatternResourceType; }
</span><span class="cx">
</span><ins>+ void collectPatternAttributes(PatternAttributes&) const;
+
</ins><span class="cx"> private:
</span><span class="cx"> void element() const = delete;
</span><span class="cx"> virtual const char* renderName() const override { return "RenderSVGResourcePattern"; }
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingsvgRenderSVGRootcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/svg/RenderSVGRoot.cpp (191730 => 191731)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/svg/RenderSVGRoot.cpp        2015-10-29 16:51:41 UTC (rev 191730)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGRoot.cpp        2015-10-29 17:12:43 UTC (rev 191731)
</span><span class="lines">@@ -180,9 +180,10 @@
</span><span class="cx">
</span><span class="cx"> if (!m_resourcesNeedingToInvalidateClients.isEmpty()) {
</span><span class="cx"> // Invalidate resource clients, which may mark some nodes for layout.
</span><del>- HashSet<RenderSVGResourceContainer*>::iterator end = m_resourcesNeedingToInvalidateClients.end();
- for (HashSet<RenderSVGResourceContainer*>::iterator it = m_resourcesNeedingToInvalidateClients.begin(); it != end; ++it)
- (*it)->removeAllClientsFromCache();
</del><ins>+ for (auto& resource : m_resourcesNeedingToInvalidateClients) {
+ resource->removeAllClientsFromCache();
+ SVGResourcesCache::clientStyleChanged(*resource, StyleDifferenceLayout, resource->style());
+ }
</ins><span class="cx">
</span><span class="cx"> m_isLayoutSizeChanged = false;
</span><span class="cx"> SVGRenderSupport::layoutChildren(*this, false);
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingsvgSVGRenderTreeAsTextcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp (191730 => 191731)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp        2015-10-29 16:51:41 UTC (rev 191730)
+++ trunk/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp        2015-10-29 17:12:43 UTC (rev 191731)
</span><span class="lines">@@ -432,7 +432,7 @@
</span><span class="cx"> // Dump final results that are used for rendering. No use in asking SVGPatternElement for its patternUnits(), as it may
</span><span class="cx"> // link to other patterns using xlink:href, we need to build the full inheritance chain, aka. collectPatternProperties()
</span><span class="cx"> PatternAttributes attributes;
</span><del>- pattern.patternElement().collectPatternAttributes(attributes);
</del><ins>+ pattern.collectPatternAttributes(attributes);
</ins><span class="cx">
</span><span class="cx"> writeNameValuePair(ts, "patternUnits", attributes.patternUnits());
</span><span class="cx"> writeNameValuePair(ts, "patternContentUnits", attributes.patternContentUnits());
</span></span></pre></div>
<a id="trunkSourceWebCoresvgSVGPatternElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/SVGPatternElement.cpp (191730 => 191731)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/svg/SVGPatternElement.cpp        2015-10-29 16:51:41 UTC (rev 191730)
+++ trunk/Source/WebCore/svg/SVGPatternElement.cpp        2015-10-29 17:12:43 UTC (rev 191731)
</span><span class="lines">@@ -187,65 +187,42 @@
</span><span class="cx"> return createRenderer<RenderSVGResourcePattern>(*this, WTF::move(style));
</span><span class="cx"> }
</span><span class="cx">
</span><del>-static void setPatternAttributes(const SVGPatternElement& element, PatternAttributes& attributes)
</del><ins>+void SVGPatternElement::collectPatternAttributes(PatternAttributes& attributes) const
</ins><span class="cx"> {
</span><del>- if (!attributes.hasX() && element.hasAttribute(SVGNames::xAttr))
- attributes.setX(element.x());
</del><ins>+ if (!attributes.hasX() && hasAttribute(SVGNames::xAttr))
+ attributes.setX(x());
</ins><span class="cx">
</span><del>- if (!attributes.hasY() && element.hasAttribute(SVGNames::yAttr))
- attributes.setY(element.y());
</del><ins>+ if (!attributes.hasY() && hasAttribute(SVGNames::yAttr))
+ attributes.setY(y());
</ins><span class="cx">
</span><del>- if (!attributes.hasWidth() && element.hasAttribute(SVGNames::widthAttr))
- attributes.setWidth(element.width());
</del><ins>+ if (!attributes.hasWidth() && hasAttribute(SVGNames::widthAttr))
+ attributes.setWidth(width());
</ins><span class="cx">
</span><del>- if (!attributes.hasHeight() && element.hasAttribute(SVGNames::heightAttr))
- attributes.setHeight(element.height());
</del><ins>+ if (!attributes.hasHeight() && hasAttribute(SVGNames::heightAttr))
+ attributes.setHeight(height());
</ins><span class="cx">
</span><del>- if (!attributes.hasViewBox() && element.hasAttribute(SVGNames::viewBoxAttr) && element.viewBoxIsValid())
- attributes.setViewBox(element.viewBox());
</del><ins>+ if (!attributes.hasViewBox() && hasAttribute(SVGNames::viewBoxAttr) && viewBoxIsValid())
+ attributes.setViewBox(viewBox());
</ins><span class="cx">
</span><del>- if (!attributes.hasPreserveAspectRatio() && element.hasAttribute(SVGNames::preserveAspectRatioAttr))
- attributes.setPreserveAspectRatio(element.preserveAspectRatio());
</del><ins>+ if (!attributes.hasPreserveAspectRatio() && hasAttribute(SVGNames::preserveAspectRatioAttr))
+ attributes.setPreserveAspectRatio(preserveAspectRatio());
</ins><span class="cx">
</span><del>- if (!attributes.hasPatternUnits() && element.hasAttribute(SVGNames::patternUnitsAttr))
- attributes.setPatternUnits(element.patternUnits());
</del><ins>+ if (!attributes.hasPatternUnits() && hasAttribute(SVGNames::patternUnitsAttr))
+ attributes.setPatternUnits(patternUnits());
</ins><span class="cx">
</span><del>- if (!attributes.hasPatternContentUnits() && element.hasAttribute(SVGNames::patternContentUnitsAttr))
- attributes.setPatternContentUnits(element.patternContentUnits());
</del><ins>+ if (!attributes.hasPatternContentUnits() && hasAttribute(SVGNames::patternContentUnitsAttr))
+ attributes.setPatternContentUnits(patternContentUnits());
</ins><span class="cx">
</span><del>- if (!attributes.hasPatternTransform() && element.hasAttribute(SVGNames::patternTransformAttr)) {
</del><ins>+ if (!attributes.hasPatternTransform() && hasAttribute(SVGNames::patternTransformAttr)) {
</ins><span class="cx"> AffineTransform transform;
</span><del>- element.patternTransform().concatenate(transform);
</del><ins>+ patternTransform().concatenate(transform);
</ins><span class="cx"> attributes.setPatternTransform(transform);
</span><span class="cx"> }
</span><span class="cx">
</span><del>- if (!attributes.hasPatternContentElement() && element.childElementCount())
- attributes.setPatternContentElement(&element);
</del><ins>+ if (!attributes.hasPatternContentElement() && childElementCount())
+ attributes.setPatternContentElement(this);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void SVGPatternElement::collectPatternAttributes(PatternAttributes& attributes) const
-{
- HashSet<const SVGPatternElement*> processedPatterns;
- const SVGPatternElement* current = this;
-
- while (true) {
- setPatternAttributes(*current, attributes);
- processedPatterns.add(current);
-
- // Respect xlink:href, take attributes from referenced element
- Element* refElement = SVGURIReference::targetElementFromIRIString(current->href(), document());
- if (is<SVGPatternElement>(refElement)) {
- current = downcast<SVGPatternElement>(refElement);
-
- // Cycle detection
- if (processedPatterns.contains(current))
- return;
- } else
- return;
- }
- ASSERT_NOT_REACHED();
-}
-
</del><span class="cx"> AffineTransform SVGPatternElement::localCoordinateSpaceTransform(SVGLocatable::CTMScope) const
</span><span class="cx"> {
</span><span class="cx"> AffineTransform matrix;
</span></span></pre>
</div>
</div>
</body>
</html>