[librsvg: 14/53] Make <use> with circular references render nothing, instead of exiting early
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 14/53] Make <use> with circular references render nothing, instead of exiting early
- Date: Fri, 23 Oct 2020 02:19:06 +0000 (UTC)
commit e0ad4b2ebee83bb7493d25cd799009ed92c15c43
Author: Federico Mena Quintero <federico gnome org>
Date: Tue Oct 13 18:09:37 2020 -0500
Make <use> with circular references render nothing, instead of exiting early
https://www.w3.org/TR/SVG2/struct.html#UseElement says this:
If the referenced element is a (shadow-including) ancestor of the
‘use’ element, then this is an invalid circular reference and the
‘use’ element is in error.
So, we'll just render nothing instead of exiting early with a
CircularReference error, as is customary for elements in error.
This moves the 308-*.svg tests to Rust, and removes them from the C tests.
librsvg_crate/tests/standalone/bugs.rs | 87 +++++++++++++++++++++-
rsvg_internals/src/drawing_ctx.rs | 16 ++--
tests/errors.c | 13 ----
tests/fixtures/errors/308-doubly-recursive-use.svg | 13 ----
tests/fixtures/errors/308-recursive-use.svg | 9 ---
tests/fixtures/errors/308-use-self-ref.svg | 7 --
6 files changed, 95 insertions(+), 50 deletions(-)
---
diff --git a/librsvg_crate/tests/standalone/bugs.rs b/librsvg_crate/tests/standalone/bugs.rs
index 3e5a9eec..1debc7e6 100644
--- a/librsvg_crate/tests/standalone/bugs.rs
+++ b/librsvg_crate/tests/standalone/bugs.rs
@@ -1,5 +1,5 @@
use cairo;
-use librsvg::LoadingError;
+use librsvg::{LoadingError, SvgHandle};
use matches::matches;
use rsvg_internals::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
@@ -251,3 +251,88 @@ fn recursive_paint_servers_fallback_to_color() {
"recursive_paint_servers_fallback_to_color",
);
}
+
+fn test_renders_as_empty(svg: &SvgHandle, test_name: &str) {
+ let output_surf = render_document(
+ &svg,
+ SurfaceSize(100, 100),
+ |_| (),
+ cairo::Rectangle {
+ x: 0.0,
+ y: 0.0,
+ width: 100.0,
+ height: 100.0,
+ },
+ )
+ .unwrap();
+
+ let reference_surf = cairo::ImageSurface::create(cairo::Format::ARgb32, 100, 100).unwrap();
+ let reference_surf = SharedImageSurface::wrap(reference_surf, SurfaceType::SRgb).unwrap();
+
+ compare_to_surface(&output_surf, &reference_surf, test_name);
+}
+
+// https://gitlab.gnome.org/GNOME/librsvg/-/issues/308
+#[test]
+fn recursive_use() {
+ let svg = load_svg(
+ br##"<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <g id="one">
+ <use xlink:href="#one"/>
+ </g>
+ </defs>
+
+ <use xlink:href="#one"/>
+</svg>
+"##,
+ )
+ .unwrap();
+
+ test_renders_as_empty(&svg, "308-recursive-use");
+}
+
+// https://gitlab.gnome.org/GNOME/librsvg/-/issues/308
+#[test]
+fn use_self_ref() {
+ let svg = load_svg(
+ br##"<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <use id="one" xlink:href="#one"/>
+ </defs>
+
+ <use xlink:href="#one"/>
+</svg>
+"##,
+ )
+ .unwrap();
+
+ test_renders_as_empty(&svg, "308-use-self-ref");
+}
+
+// https://gitlab.gnome.org/GNOME/librsvg/-/issues/308
+#[test]
+fn doubly_recursive_use() {
+ let svg = load_svg(
+ br##"<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <g id="one">
+ <use xlink:href="#two"/>
+ </g>
+
+ <g id="two">
+ <use xlink:href="#one"/>
+ </g>
+ </defs>
+
+ <use xlink:href="#one"/>
+</svg>
+"##,
+ )
+ .unwrap();
+
+ test_renders_as_empty(&svg, "308-doubly-recursive-use");
+}
diff --git a/rsvg_internals/src/drawing_ctx.rs b/rsvg_internals/src/drawing_ctx.rs
index f4431e4b..c56effb5 100644
--- a/rsvg_internals/src/drawing_ctx.rs
+++ b/rsvg_internals/src/drawing_ctx.rs
@@ -1645,14 +1645,16 @@ impl DrawingCtx {
// another <use> which references the first one, etc.). So,
// we acquire the <use> element itself so that circular
// references can be caught.
- let _self_acquired = acquired_nodes.acquire_ref(node).map_err(|e| {
- if let AcquireError::CircularReference(_) = e {
+ let _self_acquired = match acquired_nodes.acquire_ref(node) {
+ Ok(n) => n,
+
+ Err(AcquireError::CircularReference(_)) => {
rsvg_log!("circular reference in element {}", node);
- RenderingError::CircularReference
- } else {
- unreachable!();
+ return Ok(self.empty_bbox());
}
- })?;
+
+ _ => unreachable!(),
+ };
if link.is_none() {
return Ok(self.empty_bbox());
@@ -1663,7 +1665,7 @@ impl DrawingCtx {
Err(AcquireError::CircularReference(node)) => {
rsvg_log!("circular reference in element {}", node);
- return Err(RenderingError::CircularReference);
+ return Ok(self.empty_bbox());
}
Err(AcquireError::MaxReferencesExceeded) => {
diff --git a/tests/errors.c b/tests/errors.c
index 9173d833..e476d63f 100644
--- a/tests/errors.c
+++ b/tests/errors.c
@@ -62,18 +62,5 @@ main (int argc, char **argv)
test_instancing_limit,
NULL);
- g_test_add_data_func_full ("/errors/instancing_limit/308-use-self-ref.svg",
- "308-use-self-ref.svg",
- test_instancing_limit,
- NULL);
- g_test_add_data_func_full ("/errors/instancing_limit/308-recursive-use.svg",
- "308-recursive-use.svg",
- test_instancing_limit,
- NULL);
- g_test_add_data_func_full ("/errors/instancing_limit/308-doubly-recursive-use.svg",
- "308-doubly-recursive-use.svg",
- test_instancing_limit,
- NULL);
-
return g_test_run ();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]