diff options
author | Federico Mena Quintero <federico@gnome.org> | 2023-03-14 03:12:10 +0000 |
---|---|---|
committer | Federico Mena Quintero <federico@gnome.org> | 2023-03-14 03:12:10 +0000 |
commit | e357c9d0482db62afc891273996a118e02b0d7fb (patch) | |
tree | dcf06c76bba8c9071d4a263ee393f8de156b2f9b | |
parent | a4fe5d9f3c1692d4d36af30947c506d9273fd44f (diff) | |
parent | c50e8cef0697848268bfed5f222e3d8bc1096728 (diff) | |
download | librsvg-e357c9d0482db62afc891273996a118e02b0d7fb.tar.gz |
Merge branch 'xinclude-recursion-2.55' into 'librsvg-2.55'
(#942): Fix crash when XML files get recursively included through XInclude
See merge request GNOME/librsvg!809
-rw-r--r-- | src/limits.rs | 10 | ||||
-rw-r--r-- | src/xml/mod.rs | 34 | ||||
-rw-r--r-- | tests/fixtures/crash/bug942-xinclude-mutual-recursion-2.svg | 3 | ||||
-rw-r--r-- | tests/fixtures/crash/bug942-xinclude-mutual-recursion.svg | 3 | ||||
-rw-r--r-- | tests/fixtures/crash/bug942-xinclude-recursion.svg | 3 |
5 files changed, 51 insertions, 2 deletions
diff --git a/src/limits.rs b/src/limits.rs index 89e33da0..e287767b 100644 --- a/src/limits.rs +++ b/src/limits.rs @@ -40,3 +40,13 @@ pub const MAX_LOADED_ELEMENTS: usize = 1_000_000; /// of attributes that the SVG standard ascribes meaning to are lower than /// this limit. pub const MAX_LOADED_ATTRIBUTES: usize = u16::MAX as usize; + +/// Maximum level of nesting for XInclude (XML Include) files. +/// +/// See <https://gitlab.gnome.org/GNOME/librsvg/-/issues/942>. With +/// the use of XML like `<xi:include parse="xml" href="foo.xml"/>`, an +/// SVG document can recursively include other XML files. This value +/// defines a maximum level of nesting for XInclude, to prevent cases +/// where the base document is included within itself, or when two +/// documents recursively include each other. +pub const MAX_XINCLUDE_DEPTH: usize = 20; diff --git a/src/xml/mod.rs b/src/xml/mod.rs index a9ccffac..c7493455 100644 --- a/src/xml/mod.rs +++ b/src/xml/mod.rs @@ -25,7 +25,7 @@ use crate::document::{Document, DocumentBuilder}; use crate::error::{ImplementationLimit, LoadingError}; use crate::handle::LoadOptions; use crate::io::{self, IoError}; -use crate::limits::MAX_LOADED_ELEMENTS; +use crate::limits::{MAX_LOADED_ELEMENTS, MAX_XINCLUDE_DEPTH}; use crate::node::{Node, NodeBorrow}; use crate::style::StyleType; use crate::url_resolver::AllowedUrl; @@ -106,6 +106,7 @@ struct XmlStateInner { weak: Option<Weak<XmlState>>, document_builder: Option<DocumentBuilder>, num_loaded_elements: usize, + xinclude_depth: usize, context_stack: Vec<Context>, current_node: Option<Node>, @@ -144,6 +145,7 @@ impl XmlState { weak: None, document_builder: Some(document_builder), num_loaded_elements: 0, + xinclude_depth: 0, context_stack: vec![Context::Start], current_node: None, entities: HashMap::new(), @@ -546,7 +548,7 @@ impl XmlState { // the absence of a default value declaration). Values // other than "xml" and "text" are a fatal error." match parse { - None | Some("xml") => self.acquire_xml(&aurl), + None | Some("xml") => self.include_xml(&aurl), Some("text") => self.acquire_text(&aurl, encoding), @@ -565,6 +567,34 @@ impl XmlState { } } + fn include_xml(&self, aurl: &AllowedUrl) -> Result<(), AcquireError> { + self.increase_xinclude_depth(aurl)?; + + let result = self.acquire_xml(aurl); + + self.decrease_xinclude_depth(); + + result + } + + fn increase_xinclude_depth(&self, aurl: &AllowedUrl) -> Result<(), AcquireError> { + let mut inner = self.inner.borrow_mut(); + + if inner.xinclude_depth == MAX_XINCLUDE_DEPTH { + Err(AcquireError::FatalError(format!( + "exceeded maximum level of nested xinclude in {aurl}" + ))) + } else { + inner.xinclude_depth += 1; + Ok(()) + } + } + + fn decrease_xinclude_depth(&self) { + let mut inner = self.inner.borrow_mut(); + inner.xinclude_depth -= 1; + } + fn acquire_text(&self, aurl: &AllowedUrl, encoding: Option<&str>) -> Result<(), AcquireError> { let session = self .inner diff --git a/tests/fixtures/crash/bug942-xinclude-mutual-recursion-2.svg b/tests/fixtures/crash/bug942-xinclude-mutual-recursion-2.svg new file mode 100644 index 00000000..4445f6c4 --- /dev/null +++ b/tests/fixtures/crash/bug942-xinclude-mutual-recursion-2.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xi="http://www.w3.org/2001/XInclude"> + <xi:include parse="xml" href="bug942-xinclude-mutual-recursion.svg"/> +</svg> diff --git a/tests/fixtures/crash/bug942-xinclude-mutual-recursion.svg b/tests/fixtures/crash/bug942-xinclude-mutual-recursion.svg new file mode 100644 index 00000000..4f7fb734 --- /dev/null +++ b/tests/fixtures/crash/bug942-xinclude-mutual-recursion.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xi="http://www.w3.org/2001/XInclude"> + <xi:include parse="xml" href="bug942-xinclude-mutual-recursion-2.svg"/> +</svg> diff --git a/tests/fixtures/crash/bug942-xinclude-recursion.svg b/tests/fixtures/crash/bug942-xinclude-recursion.svg new file mode 100644 index 00000000..039639da --- /dev/null +++ b/tests/fixtures/crash/bug942-xinclude-recursion.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xi="http://www.w3.org/2001/XInclude"> + <xi:include parse="xml" href=""/> +</svg> |