diff --git a/crates/docx/src/read/embed.rs b/crates/docx/src/read/embed.rs
index ce4eae7ed..1cc97bb03 100644
--- a/crates/docx/src/read/embed.rs
+++ b/crates/docx/src/read/embed.rs
@@ -395,7 +395,7 @@ mod tests {
// A hyperlink whose relationship id is written without the prefix: the reader resolves
// it (the alias `El::attr` accepts), so the part it names is not carried over twice.
let named = package(
- r#"link"#,
+ r#"link"#,
&[("rIdDoc1", "keep.bin")],
&[("word/keep.bin", b"kept")],
);
diff --git a/crates/docx/src/xml.rs b/crates/docx/src/xml.rs
index d1aa38a91..6fd1db7e9 100644
--- a/crates/docx/src/xml.rs
+++ b/crates/docx/src/xml.rs
@@ -346,6 +346,9 @@ fn parse_with(bytes: &[u8], extra: &[(&'static str, &str)], strict: bool) -> Res
};
match ev {
Event::Start(ref e) | Event::Empty(ref e) => {
+ if strict && root.is_some() && stack.is_empty() {
+ return Err(DocxError::Xml("more than one root element".into()));
+ }
count += 1;
if count > MAX_ELEMENTS {
return Err(DocxError::Limit("too many XML elements".into()));
@@ -433,15 +436,17 @@ fn parse_with(bytes: &[u8], extra: &[(&'static str, &str)], strict: bool) -> Res
}
Err(_) => None,
};
- if let Some(c) = ch {
- push_text(top, &c);
+ match ch {
+ Some(c) => push_text(top, &c),
+ None if strict => return Err(DocxError::Xml("an entity is not defined".into())),
+ None => {}
}
}
}
Event::Eof => break,
_ => {}
}
- if root.is_some() && stack.is_empty() {
+ if !strict && root.is_some() && stack.is_empty() {
break;
}
}
@@ -567,6 +572,22 @@ pub fn body_ns() -> Vec<(String, String)> {
mod tests {
use super::*;
+ #[test]
+ fn strict_parsing_rejects_a_dropped_entity_and_trailing_markup() {
+ let bad = [&b"before &unknown; after"[..], b"", b""];
+ for xml in bad {
+ assert!(parse_strict(xml).is_err(), "{}", String::from_utf8_lossy(xml));
+ }
+ assert!(
+ parse_strict(
+ b"x & y
+"
+ )
+ .is_ok()
+ );
+ assert!(parse(b"").is_ok(), "lenient parsing still stops at the root");
+ }
+
#[test]
fn a_relationship_attribute_is_the_namespaced_one_or_the_alias_of_one() {
// The relationship namespace, and VML's `o:relid`.