Use pre-resolved resource in SVGPatternElement::ReferencedElement
SVGPatternElement::BuildPendingResource() resolves a resource reference
for 'href' on the <pattern> element using the TreeScope-based "resource
store". SVGPatternElement::ReferencedElement() (re-)resolves the same
reference on its own. Because of this inconsistency we could end up
having a reference to a LayoutObject in the associated SVGResources
object, but not have hooked up a client reference for the (originating)
<pattern> element.
Use the SVGResource to resolve the target element in ReferencedElement()
too so that there's only one source of truth.
Bug: 949015
Change-Id: I001c4f9260bdc4599843cd53833b749fd320daa5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1550426
Reviewed-by: Stephen Chenney <schenney@chromium.org>
Commit-Queue: Fredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/master@{#647295}
diff --git a/third_party/blink/renderer/core/svg/svg_pattern_element.cc b/third_party/blink/renderer/core/svg/svg_pattern_element.cc
index 96f3536..f6213d5 100644
--- a/third_party/blink/renderer/core/svg/svg_pattern_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_pattern_element.cc
@@ -246,8 +246,7 @@
}
const SVGPatternElement* SVGPatternElement::ReferencedElement() const {
- return ToSVGPatternElementOrNull(
- TargetElementFromIRIString(HrefString(), GetTreeScope()));
+ return ToSVGPatternElementOrNull(resource_ ? resource_->Target() : nullptr);
}
void SVGPatternElement::CollectPatternAttributes(
diff --git a/third_party/blink/web_tests/external/wpt/svg/pservers/pattern-with-invalid-base-cloned-crash.html b/third_party/blink/web_tests/external/wpt/svg/pservers/pattern-with-invalid-base-cloned-crash.html
new file mode 100644
index 0000000..04a45354
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/svg/pservers/pattern-with-invalid-base-cloned-crash.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<base id="base" href="invalid:">
+<svg id="svg">
+ <pattern id="pat" xlink:href="#pat"/>
+</svg>
+<script>
+ async_test(t => {
+ onload = t.step_func_done(() => {
+ let pattern = document.getElementById("pat");
+ base.href = "";
+ document.body.insertBefore(document.getElementById("svg").cloneNode(true),
+ document.body.firstChild);
+ document.body.offsetTop;
+ pattern.setAttribute("clip-rule", "evenodd");
+ document.body.offsetTop;
+ pattern.setAttribute("width", "0");
+ document.getElementById("svg").setAttribute("systemLanguage", "x-nonexistent");
+ document.body.offsetTop;
+ });
+ });
+</script>