mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-27 11:37:02 -06:00
SVG: non-finite viewBox and nested sizes no longer panic the importer
This commit is contained in:
@@ -789,8 +789,8 @@ impl<'a, 'i> Parser<'a, 'i> {
|
||||
// Nested viewport.
|
||||
let x = self.attr_len(n, "x", 'x', &st);
|
||||
let y = self.attr_len(n, "y", 'y', &st);
|
||||
let w = n.attribute("width").and_then(|v| self.length(v, 'x', st.font_size)).unwrap_or(self.vw);
|
||||
let h = n.attribute("height").and_then(|v| self.length(v, 'y', st.font_size)).unwrap_or(self.vh);
|
||||
let w = n.attribute("width").and_then(|v| self.length(v, 'x', st.font_size)).filter(|v| v.is_finite()).unwrap_or(self.vw);
|
||||
let h = n.attribute("height").and_then(|v| self.length(v, 'y', st.font_size)).filter(|v| v.is_finite()).unwrap_or(self.vh);
|
||||
let vb = viewbox_transform(n, w, h);
|
||||
let mut children = vec![];
|
||||
let saved = (self.vw, self.vh);
|
||||
@@ -926,7 +926,7 @@ impl<'a, 'i> Parser<'a, 'i> {
|
||||
}
|
||||
"rect" => {
|
||||
let (w, h) = (l("width", 'x'), l("height", 'y'));
|
||||
if w <= 0.0 || h <= 0.0 {
|
||||
if !(w > 0.0 && h > 0.0) {
|
||||
return None;
|
||||
}
|
||||
let rx_a = n.attribute("rx").and_then(|v| self.length(v, 'x', st.font_size));
|
||||
@@ -981,7 +981,7 @@ impl<'a, 'i> Parser<'a, 'i> {
|
||||
|
||||
fn viewbox(n: roxmltree::Node) -> Option<([f64; 2], f64, f64)> {
|
||||
let v = pathdata::numbers(n.attribute("viewBox")?);
|
||||
(v.len() == 4 && v[2] > 0.0 && v[3] > 0.0).then(|| ([v[0], v[1]], v[2], v[3]))
|
||||
(v.len() == 4 && v.iter().all(|x| x.is_finite()) && v[2] > 0.0 && v[3] > 0.0).then(|| ([v[0], v[1]], v[2], v[3]))
|
||||
}
|
||||
|
||||
/// The viewBox → viewport transform (`preserveAspectRatio`, default `xMidYMid meet`).
|
||||
|
||||
@@ -119,6 +119,45 @@ fn nested_svg_percentages_use_the_nearest_viewport() {
|
||||
assert_eq!(px(&img, 55, 65)[3], 0.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn non_finite_viewboxes_do_not_panic_or_produce_nan_geometry() {
|
||||
for attrs in ["viewBox=\"0 0 1e400 100\"", "viewBox=\"0 0 100 1e400\"", "viewBox=\"-1e400 0 100 100\""] {
|
||||
for shape in ["<rect width=\"0%\" height=\"50%\"/>", "<circle r=\"0%\"/>"] {
|
||||
let svg = format!(r#"<svg xmlns="http://www.w3.org/2000/svg" {attrs}>{shape}<rect width="50%" height="50%"/></svg>"#);
|
||||
let d = parse(svg.as_bytes()).unwrap();
|
||||
assert_eq!((d.width, d.height), (300.0, 150.0));
|
||||
let shapes = d.flatten();
|
||||
assert_eq!(shapes.len(), 1);
|
||||
assert!(matches!(shapes[0].2.geom, Geom::Rect { x, y, w, h, rx, ry }
|
||||
if [x, y, w, h, rx, ry].iter().all(|v| v.is_finite()) && w == 150.0 && h == 75.0));
|
||||
assert!(shapes[0].0.as_coeffs().iter().all(|v| v.is_finite()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn non_finite_nested_viewports_do_not_panic_or_produce_nan_geometry() {
|
||||
for attrs in ["width=\"1e400\" height=\"10\"", "width=\"10\" height=\"1e400\""] {
|
||||
for shape in ["<rect width=\"0%\" height=\"50%\"/>", "<circle r=\"0%\"/>"] {
|
||||
let svg = format!(r#"<svg xmlns="http://www.w3.org/2000/svg"><svg {attrs}>{shape}<rect width="50%" height="50%"/></svg></svg>"#);
|
||||
let d = parse(svg.as_bytes()).unwrap();
|
||||
let shapes = d.flatten();
|
||||
assert_eq!(shapes.len(), 1);
|
||||
assert!(matches!(shapes[0].2.geom, Geom::Rect { x, y, w, h, rx, ry }
|
||||
if [x, y, w, h, rx, ry].iter().all(|v| v.is_finite()) && w > 0.0 && h > 0.0));
|
||||
assert!(shapes[0].0.as_coeffs().iter().all(|v| v.is_finite()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zero_size_nested_viewport_draws_nothing() {
|
||||
for attrs in ["width=\"0\" height=\"10\"", "width=\"10\" height=\"0\""] {
|
||||
let svg = format!(r#"<svg xmlns="http://www.w3.org/2000/svg"><svg {attrs}><rect width="50%" height="50%"/></svg></svg>"#);
|
||||
assert!(parse(svg.as_bytes()).unwrap().flatten().is_empty(), "{attrs}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn malformed_input() {
|
||||
assert!(parse(b"<html/>").is_err());
|
||||
|
||||
Reference in New Issue
Block a user