On 22/07/2020 13:19, Emilio Pozuelo Monfort wrote: > So I have gone with the minimal backport to 2.44.10 instead (which I've > also tested) and it's already uploaded. debdiff attached.
Attached for real now. Emilio
diff -Nru librsvg-2.44.10/debian/changelog librsvg-2.44.10/debian/changelog --- librsvg-2.44.10/debian/changelog 2019-04-25 21:55:18.000000000 +0200 +++ librsvg-2.44.10/debian/changelog 2020-07-22 13:11:57.000000000 +0200 @@ -1,3 +1,9 @@ +librsvg (2.44.10-2.1+deb10u1) buster; urgency=medium + + * CVE-2019-20446: DoS via billion laughs attack. + + -- Emilio Pozuelo Monfort <po...@debian.org> Wed, 22 Jul 2020 13:11:57 +0200 + librsvg (2.44.10-2.1) unstable; urgency=high * Non-maintainer upload. diff -Nru librsvg-2.44.10/debian/patches/0001-limits.rs-New-file-move-the-constant-for-maximum-ins.patch librsvg-2.44.10/debian/patches/0001-limits.rs-New-file-move-the-constant-for-maximum-ins.patch --- librsvg-2.44.10/debian/patches/0001-limits.rs-New-file-move-the-constant-for-maximum-ins.patch 1970-01-01 01:00:00.000000000 +0100 +++ librsvg-2.44.10/debian/patches/0001-limits.rs-New-file-move-the-constant-for-maximum-ins.patch 2020-07-11 20:11:58.000000000 +0200 @@ -0,0 +1,79 @@ +From c5738c7716f66e66ba23aa169e79eb478b7804c5 Mon Sep 17 00:00:00 2001 +From: Federico Mena Quintero <feder...@gnome.org> +Date: Thu, 10 Oct 2019 15:16:19 -0500 +Subject: [PATCH 1/5] limits.rs - New file; move the constant for maximum + instanced nodes here + +--- + Makefile.am | 1 + + rsvg_internals/src/drawing_ctx.rs | 3 ++- + rsvg_internals/src/lib.rs | 1 + + rsvg_internals/src/limits.rs | 11 +++++++++++ + 4 files changed, 15 insertions(+), 1 deletion(-) + create mode 100644 rsvg_internals/src/limits.rs + +diff --git a/Makefile.am b/Makefile.am +index e075c958..bb181dc2 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -81,6 +81,7 @@ RUST_SRC = \ + rsvg_internals/src/iri.rs \ + rsvg_internals/src/length.rs \ + rsvg_internals/src/lib.rs \ ++ rsvg_internals/src/limits.rs \ + rsvg_internals/src/log.rs \ + rsvg_internals/src/link.rs \ + rsvg_internals/src/load.rs \ +diff --git a/rsvg_internals/src/drawing_ctx.rs b/rsvg_internals/src/drawing_ctx.rs +index 9bf9d295..c9c2d169 100644 +--- a/rsvg_internals/src/drawing_ctx.rs ++++ b/rsvg_internals/src/drawing_ctx.rs +@@ -19,6 +19,7 @@ use error::RenderingError; + use filters; + use float_eq_cairo::ApproxEqCairo; + use length::Dasharray; ++use limits; + use mask::NodeMask; + use node::{CascadedValues, NodeType, RsvgNode}; + use paint_server::{self, PaintServer}; +@@ -863,7 +864,7 @@ impl<'a> DrawingCtx<'a> { + } + + fn check_limits(&self) -> Result<(), RenderingError> { +- if self.num_elements_rendered_through_use > 500_000 { ++ if self.num_elements_rendered_through_use > limits::MAX_REFERENCED_ELEMENTS { + Err(RenderingError::InstancingLimit) + } else { + Ok(()) +diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs +index 1d36d394..99704df4 100644 +--- a/rsvg_internals/src/lib.rs ++++ b/rsvg_internals/src/lib.rs +@@ -113,6 +113,7 @@ mod handle; + mod image; + mod iri; + mod length; ++mod limits; + mod link; + mod load; + mod marker; +diff --git a/rsvg_internals/src/limits.rs b/rsvg_internals/src/limits.rs +new file mode 100644 +index 00000000..f5d58d95 +--- /dev/null ++++ b/rsvg_internals/src/limits.rs +@@ -0,0 +1,11 @@ ++/// This is a mitigation for the security-related bug ++/// https://gitlab.gnome.org/GNOME/librsvg/issues/323 - imagine ++/// the XML [billion laughs attack], but done by creating deeply ++/// nested groups of `<use>` elements. The first one references ++/// the second one ten times, the second one references the third ++/// one ten times, and so on. In the file given, this causes ++/// 10^17 objects to be rendered. While this does not exhaust ++/// memory, it would take a really long time. ++/// ++/// [billion laughs attack]: https://bitbucket.org/tiran/defusedxml ++pub const MAX_REFERENCED_ELEMENTS: usize = 500_000; +-- +2.20.1 + diff -Nru librsvg-2.44.10/debian/patches/0002-Rename-num_elements_rendered_through_use-to-num_elem.patch librsvg-2.44.10/debian/patches/0002-Rename-num_elements_rendered_through_use-to-num_elem.patch --- librsvg-2.44.10/debian/patches/0002-Rename-num_elements_rendered_through_use-to-num_elem.patch 1970-01-01 01:00:00.000000000 +0100 +++ librsvg-2.44.10/debian/patches/0002-Rename-num_elements_rendered_through_use-to-num_elem.patch 2020-07-11 20:11:58.000000000 +0200 @@ -0,0 +1,66 @@ +From 1b63d474943e8f1fe77757ee87f2d39502e32fda Mon Sep 17 00:00:00 2001 +From: Federico Mena Quintero <feder...@gnome.org> +Date: Thu, 10 Oct 2019 15:26:14 -0500 +Subject: [PATCH 2/5] Rename num_elements_rendered_through_use to + num_elements_acquired + +We'll change this to be the number of elements ever acquired through +DrawingCtx.acquire_node(), instead of just those being instanced +through the <use> element. It turns out one can create a pathological +SVG file that causes an exponential number of elements to be rendered, +without using <use>. +--- + rsvg_internals/src/drawing_ctx.rs | 20 ++++++-------------- + 1 file changed, 6 insertions(+), 14 deletions(-) + +diff --git a/rsvg_internals/src/drawing_ctx.rs b/rsvg_internals/src/drawing_ctx.rs +index c9c2d169..0d0e401b 100644 +--- a/rsvg_internals/src/drawing_ctx.rs ++++ b/rsvg_internals/src/drawing_ctx.rs +@@ -101,17 +101,9 @@ pub struct DrawingCtx<'a> { + dpi_x: f64, + dpi_y: f64, + +- /// This is a mitigation for the security-related bug +- /// https://gitlab.gnome.org/GNOME/librsvg/issues/323 - imagine +- /// the XML [billion laughs attack], but done by creating deeply +- /// nested groups of `<use>` elements. The first one references +- /// the second one ten times, the second one references the third +- /// one ten times, and so on. In the file given, this causes +- /// 10^17 objects to be rendered. While this does not exhaust +- /// memory, it would take a really long time. +- /// +- /// [billion laughs attack]: https://bitbucket.org/tiran/defusedxml +- num_elements_rendered_through_use: usize, ++ // This is a mitigation for SVG files that try to instance a huge number of ++ // elements via <use>, recursive patterns, etc. See limits.rs for details. ++ num_elements_acquired: usize, + + cr_stack: Vec<cairo::Context>, + cr: cairo::Context, +@@ -170,7 +162,7 @@ impl<'a> DrawingCtx<'a> { + rect, + dpi_x, + dpi_y, +- num_elements_rendered_through_use: 0, ++ num_elements_acquired: 0, + cr_stack: Vec::new(), + cr: cr.clone(), + initial_cr: cr.clone(), +@@ -860,11 +852,11 @@ impl<'a> DrawingCtx<'a> { + } + + pub fn increase_num_elements_rendered_through_use(&mut self, n: usize) { +- self.num_elements_rendered_through_use += n; ++ self.num_elements_acquired += n; + } + + fn check_limits(&self) -> Result<(), RenderingError> { +- if self.num_elements_rendered_through_use > limits::MAX_REFERENCED_ELEMENTS { ++ if self.num_elements_acquired > limits::MAX_REFERENCED_ELEMENTS { + Err(RenderingError::InstancingLimit) + } else { + Ok(()) +-- +2.20.1 + diff -Nru librsvg-2.44.10/debian/patches/0003-Keep-track-of-the-number-of-referenced-nodes.patch librsvg-2.44.10/debian/patches/0003-Keep-track-of-the-number-of-referenced-nodes.patch --- librsvg-2.44.10/debian/patches/0003-Keep-track-of-the-number-of-referenced-nodes.patch 1970-01-01 01:00:00.000000000 +0100 +++ librsvg-2.44.10/debian/patches/0003-Keep-track-of-the-number-of-referenced-nodes.patch 2020-07-11 20:11:58.000000000 +0200 @@ -0,0 +1,75 @@ +From d8e265b3a293a650399a1d4eb85d749596c10055 Mon Sep 17 00:00:00 2001 +From: Federico Mena Quintero <feder...@gnome.org> +Date: Wed, 26 Feb 2020 17:31:02 -0600 +Subject: [PATCH 3/5] Keep track of the number of referenced nodes + +--- + rsvg_internals/src/drawing_ctx.rs | 30 ++++++++++++++++++++++-------- + rsvg_internals/src/error.rs | 1 + + 2 files changed, 23 insertions(+), 8 deletions(-) + +diff --git a/rsvg_internals/src/drawing_ctx.rs b/rsvg_internals/src/drawing_ctx.rs +index 0d0e401b..6dfadc8e 100644 +--- a/rsvg_internals/src/drawing_ctx.rs ++++ b/rsvg_internals/src/drawing_ctx.rs +@@ -275,15 +275,29 @@ impl<'a> DrawingCtx<'a> { + // acquire it again. If you acquire a node "#foo" and don't release it before + // trying to acquire "foo" again, you will obtain a %NULL the second time. + pub fn get_acquired_node(&mut self, url: &str) -> Option<AcquiredNode> { +- if let Some(node) = self.defs.borrow_mut().lookup(url) { +- if !self.acquired_nodes_contains(node) { +- self.acquired_nodes.borrow_mut().push(node.clone()); +- let acq = AcquiredNode(self.acquired_nodes.clone(), node.clone()); +- return Some(acq); +- } ++ self.num_elements_acquired += 1; ++ ++ if self.num_elements_acquired > limits::MAX_REFERENCED_ELEMENTS { ++ return None; ++ } ++ ++ let mut defs_mut = self.defs.borrow_mut(); ++ ++ if let Some(node) = defs_mut.lookup(url) { ++ self.acquire_node_ref(node) ++ } else { ++ None + } ++ } + +- None ++ pub fn acquire_node_ref(&self, node: &RsvgNode) -> Option<AcquiredNode> { ++ if !self.acquired_nodes_contains(node) { ++ self.acquired_nodes.borrow_mut().push(node.clone()); ++ let acq = AcquiredNode(self.acquired_nodes.clone(), node.clone()); ++ Some(acq) ++ } else { ++ None ++ } + } + + fn acquired_nodes_contains(&self, node: &RsvgNode) -> bool { +@@ -857,7 +871,7 @@ impl<'a> DrawingCtx<'a> { + + fn check_limits(&self) -> Result<(), RenderingError> { + if self.num_elements_acquired > limits::MAX_REFERENCED_ELEMENTS { +- Err(RenderingError::InstancingLimit) ++ Err(RenderingError::MaxReferencesExceeded) + } else { + Ok(()) + } +diff --git a/rsvg_internals/src/error.rs b/rsvg_internals/src/error.rs +index df0d9b9d..6d853505 100644 +--- a/rsvg_internals/src/error.rs ++++ b/rsvg_internals/src/error.rs +@@ -91,6 +91,7 @@ pub enum RenderingError { + Cairo(cairo::Status), + CircularReference, + InstancingLimit, ++ MaxReferencesExceeded, + } + + impl From<cairo::Status> for RenderingError { +-- +2.20.1 + diff -Nru librsvg-2.44.10/debian/patches/0004-NodeUse-fix-infinite-loops-due-to-recursive-referenc.patch librsvg-2.44.10/debian/patches/0004-NodeUse-fix-infinite-loops-due-to-recursive-referenc.patch --- librsvg-2.44.10/debian/patches/0004-NodeUse-fix-infinite-loops-due-to-recursive-referenc.patch 1970-01-01 01:00:00.000000000 +0100 +++ librsvg-2.44.10/debian/patches/0004-NodeUse-fix-infinite-loops-due-to-recursive-referenc.patch 2020-07-11 20:11:58.000000000 +0200 @@ -0,0 +1,331 @@ +From 9f3432763bfe42f91415abb45bdcc89e0c8a355c Mon Sep 17 00:00:00 2001 +From: Federico Mena Quintero <feder...@gnome.org> +Date: Wed, 26 Feb 2020 17:46:05 -0600 +Subject: [PATCH 4/5] NodeUse: fix infinite loops due to recursive references + of "use" elements + +--- + rsvg_internals/src/drawing_ctx.rs | 4 - + rsvg_internals/src/structure.rs | 19 ++- + tests/errors.c | 42 +++++- + .../errors/308-doubly-recursive-use.svg | 13 ++ + tests/fixtures/errors/308-recursive-use.svg | 9 ++ + tests/fixtures/errors/308-use-self-ref.svg | 7 + + .../errors/515-pattern-billion-laughs.svg | 130 ++++++++++++++++++ + 7 files changed, 207 insertions(+), 17 deletions(-) + create mode 100644 tests/fixtures/errors/308-doubly-recursive-use.svg + create mode 100644 tests/fixtures/errors/308-recursive-use.svg + create mode 100644 tests/fixtures/errors/308-use-self-ref.svg + create mode 100644 tests/fixtures/errors/515-pattern-billion-laughs.svg + +diff --git a/rsvg_internals/src/drawing_ctx.rs b/rsvg_internals/src/drawing_ctx.rs +index 6dfadc8e..890b1ac2 100644 +--- a/rsvg_internals/src/drawing_ctx.rs ++++ b/rsvg_internals/src/drawing_ctx.rs +@@ -865,10 +865,6 @@ impl<'a> DrawingCtx<'a> { + } + } + +- pub fn increase_num_elements_rendered_through_use(&mut self, n: usize) { +- self.num_elements_acquired += n; +- } +- + fn check_limits(&self) -> Result<(), RenderingError> { + if self.num_elements_acquired > limits::MAX_REFERENCED_ELEMENTS { + Err(RenderingError::MaxReferencesExceeded) +diff --git a/rsvg_internals/src/structure.rs b/rsvg_internals/src/structure.rs +index f384413e..b7e53ce2 100644 +--- a/rsvg_internals/src/structure.rs ++++ b/rsvg_internals/src/structure.rs +@@ -297,6 +297,18 @@ impl NodeTrait for NodeUse { + + let uri = link.as_ref().unwrap(); + ++ // <use> is an element that is used directly, unlike ++ // <pattern>, which is used through a fill="url(#...)" ++ // reference. However, <use> will always reference another ++ // element, potentially itself or an ancestor of itself (or ++ // 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 = draw_ctx.acquire_node_ref(node); ++ if self_acquired.is_none() { ++ return Err(RenderingError::CircularReference); ++ } ++ + let child = if let Some(acquired) = draw_ctx.get_acquired_node(uri) { + // Here we clone the acquired child, so that we can drop the AcquiredNode as + // early as possible. This is so that the child's drawing method will be able +@@ -311,13 +323,6 @@ impl NodeTrait for NodeUse { + return Ok(()); + }; + +- if Node::is_ancestor(child.clone(), node.clone()) { +- // or, if we're <use>'ing ourselves +- return Err(RenderingError::CircularReference); +- } +- +- draw_ctx.increase_num_elements_rendered_through_use(1); +- + let params = draw_ctx.get_view_params(); + + let nx = self.x.get().normalize(values, ¶ms); +diff --git a/tests/errors.c b/tests/errors.c +index bdf6db7b..85663004 100644 +--- a/tests/errors.c ++++ b/tests/errors.c +@@ -24,9 +24,10 @@ get_test_filename (const char *basename) { + } + + static void +-test_non_svg_element (void) ++test_loading_error (gconstpointer data) + { +- char *filename = get_test_filename ("335-non-svg-element.svg"); ++ const char *basename = data; ++ char *filename = get_test_filename (basename); + RsvgHandle *handle; + GError *error = NULL; + +@@ -35,12 +36,15 @@ test_non_svg_element (void) + + g_assert (handle == NULL); + g_assert (g_error_matches (error, RSVG_ERROR, RSVG_ERROR_FAILED)); ++ ++ g_error_free (error); + } + + static void +-test_instancing_limit (void) ++test_instancing_limit (gconstpointer data) + { +- char *filename = get_test_filename ("323-nested-use.svg"); ++ const char *basename = data; ++ char *filename = get_test_filename (basename); + RsvgHandle *handle; + GError *error = NULL; + cairo_surface_t *surf; +@@ -64,8 +68,34 @@ main (int argc, char **argv) + { + g_test_init (&argc, &argv, NULL); + +- g_test_add_func ("/errors/non_svg_element", test_non_svg_element); +- g_test_add_func ("/errors/instancing_limit", test_instancing_limit); ++ g_test_add_data_func_full ("/errors/non_svg_element", ++ "335-non-svg-element.svg", ++ test_loading_error, ++ NULL); ++ ++ g_test_add_data_func_full ("/errors/instancing_limit/323-nested-use.svg", ++ "323-nested-use.svg", ++ test_instancing_limit, ++ NULL); ++ ++ g_test_add_data_func_full ("/errors/instancing_limit/515-pattern-billion-laughs.svg", ++ "515-pattern-billion-laughs.svg", ++ 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 (); + } +diff --git a/tests/fixtures/errors/308-doubly-recursive-use.svg b/tests/fixtures/errors/308-doubly-recursive-use.svg +new file mode 100644 +index 00000000..9b248a6f +--- /dev/null ++++ b/tests/fixtures/errors/308-doubly-recursive-use.svg +@@ -0,0 +1,13 @@ ++<svg> ++ <defs> ++ <g id="one"> ++ <use xlink:href="#two"/> ++ </g> ++ ++ <g id="two"> ++ <use xlink:href="#one"/> ++ </g> ++ </defs> ++ ++ <use xlink:href="#one"/> ++</svg> +diff --git a/tests/fixtures/errors/308-recursive-use.svg b/tests/fixtures/errors/308-recursive-use.svg +new file mode 100644 +index 00000000..f5d00bf2 +--- /dev/null ++++ b/tests/fixtures/errors/308-recursive-use.svg +@@ -0,0 +1,9 @@ ++<svg> ++ <defs> ++ <g id="one"> ++ <use xlink:href="#one"/> ++ </g> ++ </defs> ++ ++ <use xlink:href="#one"/> ++</svg> +diff --git a/tests/fixtures/errors/308-use-self-ref.svg b/tests/fixtures/errors/308-use-self-ref.svg +new file mode 100644 +index 00000000..dbf14c54 +--- /dev/null ++++ b/tests/fixtures/errors/308-use-self-ref.svg +@@ -0,0 +1,7 @@ ++<svg> ++ <defs> ++ <use id="one" xlink:href="#one"/> ++ </defs> ++ ++ <use xlink:href="#one"/> ++</svg> +diff --git a/tests/fixtures/errors/515-pattern-billion-laughs.svg b/tests/fixtures/errors/515-pattern-billion-laughs.svg +new file mode 100644 +index 00000000..1cb6cbe8 +--- /dev/null ++++ b/tests/fixtures/errors/515-pattern-billion-laughs.svg +@@ -0,0 +1,130 @@ ++<?xml version="1.0" standalone="no"?> ++<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" ++ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> ++<svg width="40cm" height="20cm" viewBox="0 0 800 400" version="1.1" ++ xmlns="http://www.w3.org/2000/svg"> ++ <defs> ++ <pattern id="z" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse" patternTransform="scale(10,10)"> ++ <rect x="0" y="0" width="20" height="20" fill="url(#i)" stroke="yellow"/> ++ </pattern> ++ ++ <pattern id="i" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse" patternTransform="scale(0.5,0.5)"> ++ <rect x="0" y="0" width="20" height="20" fill="url(#h)" stroke="green" /> ++ <rect x="1" y="1" width="20" height="20" fill="url(#h)" stroke="brown" /> ++ <rect x="2" y="2" width="20" height="20" fill="url(#h)" stroke="pink" /> ++ <rect x="3" y="3" width="20" height="20" fill="url(#h)" stroke="grey" /> ++ <rect x="4" y="3" width="20" height="20" fill="url(#h)" stroke="cyan" /> ++ <rect x="5" y="3" width="20" height="20" fill="url(#h)" stroke="green" /> ++ <rect x="6" y="3" width="20" height="20" fill="url(#h)" stroke="brown" /> ++ <rect x="7" y="3" width="20" height="20" fill="url(#h)" stroke="pink" /> ++ <rect x="8" y="3" width="20" height="20" fill="url(#h)" stroke="grey" /> ++ <rect x="9" y="3" width="20" height="20" fill="url(#h)" stroke="cyan" /> ++ </pattern> ++ ++ <pattern id="h" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse" patternTransform="scale(0.5,0.5)"> ++ <rect x="0" y="0" width="20" height="20" fill="url(#g)" stroke="green" /> ++ <rect x="1" y="1" width="20" height="20" fill="url(#g)" stroke="brown" /> ++ <rect x="2" y="2" width="20" height="20" fill="url(#g)" stroke="pink" /> ++ <rect x="3" y="3" width="20" height="20" fill="url(#g)" stroke="grey" /> ++ <rect x="4" y="3" width="20" height="20" fill="url(#g)" stroke="cyan" /> ++ <rect x="5" y="3" width="20" height="20" fill="url(#g)" stroke="green" /> ++ <rect x="6" y="3" width="20" height="20" fill="url(#g)" stroke="brown" /> ++ <rect x="7" y="3" width="20" height="20" fill="url(#g)" stroke="pink" /> ++ <rect x="8" y="3" width="20" height="20" fill="url(#g)" stroke="grey" /> ++ <rect x="9" y="3" width="20" height="20" fill="url(#g)" stroke="cyan" /> ++ </pattern> ++ ++ <pattern id="g" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse" patternTransform="scale(0.5,0.5)"> ++ <rect x="0" y="0" width="20" height="20" fill="url(#f)" stroke="green" /> ++ <rect x="1" y="1" width="20" height="20" fill="url(#f)" stroke="brown" /> ++ <rect x="2" y="2" width="20" height="20" fill="url(#f)" stroke="pink" /> ++ <rect x="3" y="3" width="20" height="20" fill="url(#f)" stroke="grey" /> ++ <rect x="4" y="3" width="20" height="20" fill="url(#f)" stroke="cyan" /> ++ <rect x="5" y="3" width="20" height="20" fill="url(#f)" stroke="green" /> ++ <rect x="6" y="3" width="20" height="20" fill="url(#f)" stroke="brown" /> ++ <rect x="7" y="3" width="20" height="20" fill="url(#f)" stroke="pink" /> ++ <rect x="8" y="3" width="20" height="20" fill="url(#f)" stroke="grey" /> ++ <rect x="9" y="3" width="20" height="20" fill="url(#f)" stroke="cyan" /> ++ </pattern> ++ ++ <pattern id="f" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse" patternTransform="scale(0.5,0.5)"> ++ <rect x="0" y="0" width="20" height="20" fill="url(#e)" stroke="green" /> ++ <rect x="1" y="1" width="20" height="20" fill="url(#e)" stroke="brown" /> ++ <rect x="2" y="2" width="20" height="20" fill="url(#e)" stroke="pink" /> ++ <rect x="3" y="3" width="20" height="20" fill="url(#e)" stroke="grey" /> ++ <rect x="4" y="3" width="20" height="20" fill="url(#e)" stroke="cyan" /> ++ <rect x="5" y="3" width="20" height="20" fill="url(#e)" stroke="green" /> ++ <rect x="6" y="3" width="20" height="20" fill="url(#e)" stroke="brown" /> ++ <rect x="7" y="3" width="20" height="20" fill="url(#e)" stroke="pink" /> ++ <rect x="8" y="3" width="20" height="20" fill="url(#e)" stroke="grey" /> ++ <rect x="9" y="3" width="20" height="20" fill="url(#e)" stroke="cyan" /> ++ </pattern> ++ ++ <pattern id="e" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse" patternTransform="scale(0.5,0.5)"> ++ <rect x="0" y="0" width="20" height="20" fill="url(#d)" stroke="green" /> ++ <rect x="1" y="1" width="20" height="20" fill="url(#d)" stroke="brown" /> ++ <rect x="2" y="2" width="20" height="20" fill="url(#d)" stroke="pink" /> ++ <rect x="3" y="3" width="20" height="20" fill="url(#d)" stroke="grey" /> ++ <rect x="4" y="3" width="20" height="20" fill="url(#d)" stroke="cyan" /> ++ <rect x="5" y="3" width="20" height="20" fill="url(#d)" stroke="green" /> ++ <rect x="6" y="3" width="20" height="20" fill="url(#d)" stroke="brown" /> ++ <rect x="7" y="3" width="20" height="20" fill="url(#d)" stroke="pink" /> ++ <rect x="8" y="3" width="20" height="20" fill="url(#d)" stroke="grey" /> ++ <rect x="9" y="3" width="20" height="20" fill="url(#d)" stroke="cyan" /> ++ </pattern> ++ ++ <pattern id="d" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse" patternTransform="scale(0.5,0.5)"> ++ <rect x="0" y="0" width="20" height="20" fill="url(#c)" stroke="green" /> ++ <rect x="1" y="1" width="20" height="20" fill="url(#c)" stroke="brown" /> ++ <rect x="2" y="2" width="20" height="20" fill="url(#c)" stroke="pink" /> ++ <rect x="3" y="3" width="20" height="20" fill="url(#c)" stroke="grey" /> ++ <rect x="4" y="3" width="20" height="20" fill="url(#c)" stroke="cyan" /> ++ <rect x="5" y="3" width="20" height="20" fill="url(#c)" stroke="green" /> ++ <rect x="6" y="3" width="20" height="20" fill="url(#c)" stroke="brown" /> ++ <rect x="7" y="3" width="20" height="20" fill="url(#c)" stroke="pink" /> ++ <rect x="8" y="3" width="20" height="20" fill="url(#c)" stroke="grey" /> ++ <rect x="9" y="3" width="20" height="20" fill="url(#c)" stroke="cyan" /> ++ </pattern> ++ <pattern id="c" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse" patternTransform="scale(0.5,0.5)"> ++ <rect x="0" y="0" width="20" height="20" fill="url(#b)" stroke="green" /> ++ <rect x="1" y="1" width="20" height="20" fill="url(#b)" stroke="brown" /> ++ <rect x="2" y="2" width="20" height="20" fill="url(#b)" stroke="pink" /> ++ <rect x="3" y="3" width="20" height="20" fill="url(#b)" stroke="grey" /> ++ <rect x="4" y="3" width="20" height="20" fill="url(#b)" stroke="cyan" /> ++ <rect x="5" y="3" width="20" height="20" fill="url(#b)" stroke="green" /> ++ <rect x="6" y="3" width="20" height="20" fill="url(#b)" stroke="brown" /> ++ <rect x="7" y="3" width="20" height="20" fill="url(#b)" stroke="pink" /> ++ <rect x="8" y="3" width="20" height="20" fill="url(#b)" stroke="grey" /> ++ <rect x="9" y="3" width="20" height="20" fill="url(#b)" stroke="cyan" /> ++ </pattern> ++ <pattern id="b" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse" patternTransform="scale(0.5,0.5)"> ++ <rect x="0" y="0" width="20" height="20" fill="url(#a)" stroke="green" /> ++ <rect x="1" y="1" width="20" height="20" fill="url(#a)" stroke="brown" /> ++ <rect x="2" y="2" width="20" height="20" fill="url(#a)" stroke="pink" /> ++ <rect x="3" y="3" width="20" height="20" fill="url(#a)" stroke="grey" /> ++ <rect x="4" y="3" width="20" height="20" fill="url(#a)" stroke="cyan" /> ++ <rect x="5" y="3" width="20" height="20" fill="url(#a)" stroke="green" /> ++ <rect x="6" y="3" width="20" height="20" fill="url(#a)" stroke="brown" /> ++ <rect x="7" y="3" width="20" height="20" fill="url(#a)" stroke="pink" /> ++ <rect x="8" y="3" width="20" height="20" fill="url(#a)" stroke="grey" /> ++ <rect x="9" y="3" width="20" height="20" fill="url(#a)" stroke="cyan" /> ++ ++ </pattern> ++ <pattern id="a" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse" patternTransform="scale(0.5,0.5)"> ++ <rect x="0" y="0" width="20" height="20" fill="none" stroke="green" /> ++ <rect x="1" y="1" width="20" height="20" fill="none" stroke="brown" /> ++ <rect x="2" y="2" width="20" height="20" fill="none" stroke="pink" /> ++ <rect x="3" y="3" width="20" height="20" fill="none" stroke="grey" /> ++ <rect x="4" y="3" width="20" height="20" fill="none" stroke="cyan" /> ++ <rect x="5" y="3" width="20" height="20" fill="none" stroke="green" /> ++ <rect x="6" y="3" width="20" height="20" fill="none" stroke="brown" /> ++ <rect x="7" y="3" width="20" height="20" fill="none" stroke="pink" /> ++ <rect x="8" y="3" width="20" height="20" fill="none" stroke="grey" /> ++ <rect x="9" y="3" width="20" height="20" fill="none" stroke="cyan" /> ++ </pattern> ++ </defs> ++ ++ <ellipse fill="url(#z)" stroke="black" stroke-width="5" ++ cx="400" cy="200" rx="350" ry="150" /> ++ ++</svg> +\ No newline at end of file +-- +2.20.1 + diff -Nru librsvg-2.44.10/debian/patches/0005-Limit-the-number-of-loaded-elements.patch librsvg-2.44.10/debian/patches/0005-Limit-the-number-of-loaded-elements.patch --- librsvg-2.44.10/debian/patches/0005-Limit-the-number-of-loaded-elements.patch 1970-01-01 01:00:00.000000000 +0100 +++ librsvg-2.44.10/debian/patches/0005-Limit-the-number-of-loaded-elements.patch 2020-07-11 20:17:33.000000000 +0200 @@ -0,0 +1,75 @@ +From 5edea8ca9fbecbd6c36f7fd28894e49f356d8b78 Mon Sep 17 00:00:00 2001 +From: Federico Mena Quintero <feder...@gnome.org> +Date: Wed, 26 Feb 2020 19:06:56 -0600 +Subject: [PATCH 5/5] Limit the number of loaded elements + +--- + librsvg/rsvg-load.c | 20 ++++++++++++++++++ + tests/errors.c | 4 ++++ + .../errors/515-too-many-elements.svgz | Bin 0 -> 40811 bytes + 3 files changed, 24 insertions(+) + create mode 100644 tests/fixtures/errors/515-too-many-elements.svgz + +diff --git a/librsvg/rsvg-load.c b/librsvg/rsvg-load.c +index 44e1f670..ea1e2bfb 100644 +--- a/librsvg/rsvg-load.c ++++ b/librsvg/rsvg-load.c +@@ -66,6 +66,7 @@ struct RsvgLoad { + */ + RsvgSaxHandler *handler; + int handler_nest; ++ gsize num_loaded_elements; + + GHashTable *entities; /* g_malloc'd string -> xmlEntityPtr */ + +@@ -608,12 +609,31 @@ start_xinclude (RsvgLoad *load, RsvgPropertyBag * atts) + + /* end xinclude */ + ++static gboolean ++loading_limits_exceeded (RsvgLoad *load) ++{ ++ /* This is a mitigation for SVG files which create millions of elements ++ * in an attempt to exhaust memory. We don't allow loading more than ++ * this number of elements during the initial streaming load process. ++ */ ++ return load->num_loaded_elements > 200000; ++} ++ + static void + sax_start_element_cb (void *data, const xmlChar * name, const xmlChar ** atts) + { + RsvgPropertyBag bag; + RsvgLoad *load = data; + ++ if (loading_limits_exceeded (load)) { ++ g_set_error (load->error, RSVG_ERROR, 0, "instancing limit"); ++ ++ xmlStopParser (load->ctxt); ++ return; ++ } ++ ++ load->num_loaded_elements += 1; ++ + bag = rsvg_property_bag_new ((const char **) atts); + + if (load->handler) { +diff --git a/tests/errors.c b/tests/errors.c +index 85663004..52795680 100644 +--- a/tests/errors.c ++++ b/tests/errors.c +@@ -96,6 +96,10 @@ main (int argc, char **argv) + test_instancing_limit, + NULL); + ++ g_test_add_data_func_full ("/errors/515-too-many-elements.svgz", ++ "515-too-many-elements.svgz", ++ test_loading_error, ++ NULL); + + return g_test_run (); + } + +-- +2.20.1 + diff -Nru librsvg-2.44.10/debian/patches/series librsvg-2.44.10/debian/patches/series --- librsvg-2.44.10/debian/patches/series 2019-04-25 21:54:21.000000000 +0200 +++ librsvg-2.44.10/debian/patches/series 2020-07-11 20:12:17.000000000 +0200 @@ -2,3 +2,8 @@ typenum-i386-ftbfs.patch i386-rounding-errors.patch keep-positive-radii.patch +0001-limits.rs-New-file-move-the-constant-for-maximum-ins.patch +0002-Rename-num_elements_rendered_through_use-to-num_elem.patch +0003-Keep-track-of-the-number-of-referenced-nodes.patch +0004-NodeUse-fix-infinite-loops-due-to-recursive-referenc.patch +0005-Limit-the-number-of-loaded-elements.patch diff -Nru librsvg-2.44.10/debian/source/include-binaries librsvg-2.44.10/debian/source/include-binaries --- librsvg-2.44.10/debian/source/include-binaries 1970-01-01 01:00:00.000000000 +0100 +++ librsvg-2.44.10/debian/source/include-binaries 2020-07-11 20:20:12.000000000 +0200 @@ -0,0 +1 @@ +tests/fixtures/errors/515-too-many-elements.svgz Binary files /tmp/dtBncWIUMD/librsvg-2.44.10/tests/fixtures/errors/515-too-many-elements.svgz and /tmp/pPLtG7c90L/librsvg-2.44.10/tests/fixtures/errors/515-too-many-elements.svgz differ