Commit 133cbb6c authored by Aaron Krajeski's avatar Aaron Krajeski Committed by Commit Bot

Filters containing feImage with local content no longer taint canvas.

Provide a pointer to SecurityOrigin within SVGFEImageElement so that
it can test if its content actually taints the origin. Previously all
filters with feImages tainted the canvas. When the filter is set
(during CanvasRenderingContext2DState::SetFilter) the SecurityOrigin
is stored. During CanvasRenderingContext2DState::GetFilter is it
determined whether the compiled filter should taint the canvas.

Next step is to make this work for other svg_fe elements.

Change the test expectations for SVGFEDisplacment tests as FEImages
no longer necessarily taint the origin. Reverting changes here:
https://chromium-review.googlesource.com/c/chromium/src/+/782649/

Bug: 618871
Change-Id: I506c443f842068f08eab0e3d6b214f2b10878a86
Reviewed-on: https://chromium-review.googlesource.com/c/1258968
Commit-Queue: Aaron Krajeski <aaronhk@chromium.org>
Reviewed-by: default avatarFredrik Söderquist <fs@opera.com>
Reviewed-by: default avatarRobert Flack <flackr@chromium.org>
Reviewed-by: default avatarFernando Serboncini <fserb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#608934}
parent 39d6f944
<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xhtml="http://www.w3.org/1999/xhtml" viewBox="0 0 100 100">
<foreignObject width="100" height="100">
<style>a div { background-color: green; width: 100px; height: 100px } a:link div, a:visited div { background-color: red }</style>
<xhtml:a href="http://www.example.com/"><xhtml:div></xhtml:div></xhtml:a>
</foreignObject>
</svg>
<!DOCTYPE HTML>
<html>
<head>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
</head>
<body>
<svg style="display: block; width: 0; height: 0">
<defs>
<filter id="clean-image">
<feImage href="../resources/square.png" />
</filter>
<circle id="circle" r="100" fill="blue" />
<filter id="reference-image">
<feImage href="#circle" />
</filter>
<filter id="x-origin-image">
<feImage href="http://localhost:8000/resources/square.png" />
</filter>
</defs>
</svg>
<script>
async_test((t) => {
var xOriginImage = new Image();
// Use a cross-origin URL.
xOriginImage.src = "http://localhost:8000/resources/square.png";
xOriginImage.onload = function() {
var cleanCanvas = document.createElement("canvas");
var cleanContext = cleanCanvas.getContext("2d");
cleanContext.filter = "url(#clean-image)";
cleanContext.fillRect(0, 0, 100, 100);
assert_equals(cleanContext.getImageData(0, 0, 1, 1).data[0], 0,
"Local feImage should not taint canvas");
var referenceCanvas = document.createElement("canvas");
var referenceContext = referenceCanvas.getContext("2d");
referenceContext.filter = "url(#reference-image)";
referenceContext.fillRect(0, 0, 100, 100);
assert_throws("SecurityError", () => {
referenceContext.getImageData(0, 0, 1, 1)
}, "feImage element with a reference should taint the canvas");
var xOriginCanvas = document.createElement("canvas");
var xOriginContext = xOriginCanvas.getContext("2d");
xOriginContext.filter = "url(#x-origin-image)";
xOriginContext.fillRect(0, 0, 100, 100);
assert_throws("SecurityError", () => {
xOriginContext.getImageData(0, 0, 1, 1)
}, "feImage element with a cross-origin reference should taint the \
canvas");
t.done();
};
});
</script>
</body>
</html>
\ No newline at end of file
...@@ -162,4 +162,11 @@ FilterEffect* SVGFEImageElement::Build(SVGFilterBuilder*, Filter* filter) { ...@@ -162,4 +162,11 @@ FilterEffect* SVGFEImageElement::Build(SVGFilterBuilder*, Filter* filter) {
preserve_aspect_ratio_->CurrentValue()); preserve_aspect_ratio_->CurrentValue());
} }
bool SVGFEImageElement::TaintsOrigin(bool inputs_taint_origin) const {
const SecurityOrigin* security_origin = GetDocument().GetSecurityOrigin();
if (cached_image_ && cached_image_->IsAccessAllowed(security_origin))
return inputs_taint_origin;
return true;
}
} // namespace blink } // namespace blink
...@@ -67,6 +67,7 @@ class SVGFEImageElement final : public SVGFilterPrimitiveStandardAttributes, ...@@ -67,6 +67,7 @@ class SVGFEImageElement final : public SVGFilterPrimitiveStandardAttributes,
void BuildPendingResource() override; void BuildPendingResource() override;
InsertionNotificationRequest InsertedInto(ContainerNode&) override; InsertionNotificationRequest InsertedInto(ContainerNode&) override;
void RemovedFrom(ContainerNode&) override; void RemovedFrom(ContainerNode&) override;
bool TaintsOrigin(bool inputs_taint_origin) const override;
Member<SVGAnimatedPreserveAspectRatio> preserve_aspect_ratio_; Member<SVGAnimatedPreserveAspectRatio> preserve_aspect_ratio_;
......
...@@ -359,8 +359,9 @@ sk_sp<PaintFilter> CanvasRenderingContext2DState::GetFilter( ...@@ -359,8 +359,9 @@ sk_sp<PaintFilter> CanvasRenderingContext2DState::GetFilter(
1.0f, // Deliberately ignore zoom on the canvas element. 1.0f, // Deliberately ignore zoom on the canvas element.
&fill_flags_for_filter, &stroke_flags_for_filter); &fill_flags_for_filter, &stroke_flags_for_filter);
if (FilterEffect* last_effect = filter_effect_builder.BuildFilterEffect( FilterEffect* last_effect = filter_effect_builder.BuildFilterEffect(
filter_style->Filter(), !context->OriginClean())) { filter_style->Filter(), !context->OriginClean());
if (last_effect) {
resolved_filter_ = resolved_filter_ =
paint_filter_builder::Build(last_effect, kInterpolationSpaceSRGB); paint_filter_builder::Build(last_effect, kInterpolationSpaceSRGB);
if (resolved_filter_) { if (resolved_filter_) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment