Merge pull request #2196 from Higgs32584/fix/2170-shape-font-attr-escape

xlsx: escape shape font typeface attribute (#2170)
This commit is contained in:
FredApps
2026-11-11 08:12:56 +01:00
committed by GitHub
2 changed files with 17 additions and 1 deletions
+1 -1
View File
@@ -615,7 +615,7 @@ fn run_props(f: &ShapeFormat, theme: &Theme) -> (String, String) {
let _ = write!(body, "<a:solidFill>{c}</a:solidFill>");
}
if let Some(font) = &f.font {
let _ = write!(body, "<a:latin typeface=\"{}\"/>", esc(font));
let _ = write!(body, "<a:latin typeface=\"{}\"/>", esc_attr(font));
}
(attrs, body)
}
+16
View File
@@ -85,3 +85,19 @@ fn shape_text_without_rtl_writes_unchanged_ppr() {
let xml = written_drawing(&text_box("plain", ShapeFormat::default()));
assert!(!xml.contains("<a:pPr"), "no paragraph properties without alignment or direction: {xml}");
}
/// #2170: a shape font typeface holding `"`, `<` or `&` is escaped as an attribute, so it can't
/// close the `typeface` attribute early and inject others; it survives a save and reopen.
#[test]
fn shape_font_typeface_is_attribute_escaped() {
let font = r#"a"b<c&d' injected="x"#;
let wb = text_box("hi", ShapeFormat { font: Some(font.into()), ..Default::default() });
let xml = written_drawing(&wb);
assert!(xml.contains(r#"<a:latin typeface="a&quot;b&lt;c&amp;d"#), "typeface is attribute-escaped: {xml}");
assert!(!xml.contains(r#" injected="x""#), "no attribute injected: {xml}");
let (reopened, _) = read_xlsx(&write_xlsx(&wb).unwrap()).unwrap();
let after = &reopened.sheet(0).unwrap().shapes[0];
assert_eq!(after.format.font.as_deref(), Some(font));
assert_eq!(after.text, "hi");
}