summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Mena Quintero <federico@gnome.org>2023-01-24 16:22:09 -0600
committerFederico Mena Quintero <federico@gnome.org>2023-01-24 20:24:46 -0600
commit722728cebc7eb4c13806eea4044a051e84fb826e (patch)
tree1a06661739d2da36750f8f946b47a16e82099b73
parent47ddbe5ec133c5402388b93833ecb8463142fb8b (diff)
downloadlibrsvg-722728cebc7eb4c13806eea4044a051e84fb826e.tar.gz
(#928): Fix panic when a feTile filter gets an empty source region
When the input_bounds from the filter source is empty, we tried to create a zero-sized image for tiling. This is not allowed. There is nothing to tile in that case, so just return the original image to filter. Fixes https://gitlab.gnome.org/GNOME/librsvg/-/issues/928 Part-of: <https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/787>
-rw-r--r--src/filters/mod.rs6
-rw-r--r--src/filters/tile.rs30
-rw-r--r--tests/fixtures/render-crash/bug928-empty-feTile-bounds.svg12
-rw-r--r--tests/src/render_crash.rs1
4 files changed, 41 insertions, 8 deletions
diff --git a/src/filters/mod.rs b/src/filters/mod.rs
index 1e2560c4..0bd1cefa 100644
--- a/src/filters/mod.rs
+++ b/src/filters/mod.rs
@@ -273,7 +273,11 @@ pub fn render(
)
.and_then(|mut filter_ctx| {
// the message has an unclosed parenthesis; we'll close it below.
- rsvg_log!(session, "(rendering filter with effects_region={:?}", filter_ctx.effects_region());
+ rsvg_log!(
+ session,
+ "(rendering filter with effects_region={:?}",
+ filter_ctx.effects_region()
+ );
for user_space_primitive in &filter.primitives {
let start = Instant::now();
diff --git a/src/filters/tile.rs b/src/filters/tile.rs
index 0bd4417c..e3bf940a 100644
--- a/src/filters/tile.rs
+++ b/src/filters/tile.rs
@@ -64,14 +64,30 @@ impl Tile {
surface: input_surface,
bounds: input_bounds,
}) => {
- let tile_surface = input_surface.tile(input_bounds)?;
+ if input_bounds.is_empty() {
+ rsvg_log!(
+ draw_ctx.session(),
+ "(feTile with empty input_bounds; returning just the input surface)"
+ );
- ctx.source_graphic().paint_image_tiled(
- bounds,
- &tile_surface,
- input_bounds.x0,
- input_bounds.y0,
- )?
+ input_surface
+ } else {
+ rsvg_log!(
+ draw_ctx.session(),
+ "(feTile bounds={:?}, input_bounds={:?})",
+ bounds,
+ input_bounds
+ );
+
+ let tile_surface = input_surface.tile(input_bounds)?;
+
+ ctx.source_graphic().paint_image_tiled(
+ bounds,
+ &tile_surface,
+ input_bounds.x0,
+ input_bounds.y0,
+ )?
+ }
}
};
diff --git a/tests/fixtures/render-crash/bug928-empty-feTile-bounds.svg b/tests/fixtures/render-crash/bug928-empty-feTile-bounds.svg
new file mode 100644
index 00000000..9920080f
--- /dev/null
+++ b/tests/fixtures/render-crash/bug928-empty-feTile-bounds.svg
@@ -0,0 +1,12 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
+ <filter id="filter">
+ <!-- We want to test that feTile gets an empty input region, since
+ the feFlood's bounds are outside the default filter effects
+ region.
+ -->
+ <feFlood flood-color="lime" x="50" y="50" width="10" height="10"/>
+ <feTile/>
+ </filter>
+
+ <rect x="10" y="10" width="10" height="10" filter="url(#filter)"/>
+</svg>
diff --git a/tests/src/render_crash.rs b/tests/src/render_crash.rs
index 311aa38d..da58192a 100644
--- a/tests/src/render_crash.rs
+++ b/tests/src/render_crash.rs
@@ -62,6 +62,7 @@ mod tests {
t!(bug721_pattern_cycle_from_child_svg, "bug721-pattern-cycle-from-child.svg");
t!(bug721_pattern_cycle_from_other_child_svg, "bug721-pattern-cycle-from-other-child.svg");
t!(bug777155_zero_sized_pattern_svg, "bug777155-zero-sized-pattern.svg");
+ t!(bug928_empty_fetile_bounds_svg, "bug928-empty-feTile-bounds.svg");
t!(femerge_color_interpolation_srgb_svg, "feMerge-color-interpolation-srgb.svg");
t!(filters_non_invertible_paffine_svg, "filters-non-invertible-paffine.svg");
t!(gradient_with_empty_bbox_svg, "gradient-with-empty-bbox.svg");