diff options
author | Federico Mena Quintero <federico@gnome.org> | 2023-01-24 16:22:09 -0600 |
---|---|---|
committer | Federico Mena Quintero <federico@gnome.org> | 2023-01-24 20:24:46 -0600 |
commit | 722728cebc7eb4c13806eea4044a051e84fb826e (patch) | |
tree | 1a06661739d2da36750f8f946b47a16e82099b73 | |
parent | 47ddbe5ec133c5402388b93833ecb8463142fb8b (diff) | |
download | librsvg-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.rs | 6 | ||||
-rw-r--r-- | src/filters/tile.rs | 30 | ||||
-rw-r--r-- | tests/fixtures/render-crash/bug928-empty-feTile-bounds.svg | 12 | ||||
-rw-r--r-- | tests/src/render_crash.rs | 1 |
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"); |