From 832e790ca9be2d19607480ef145b9222de82d558 Mon Sep 17 00:00:00 2001 From: NetterSilver <133535268+Silvertree2010@users.noreply.github.com> Date: Fri, 13 Nov 2026 01:43:25 +0100 Subject: [PATCH] Accept compact SVG arc flags in svg_path size check (#2299) Found while testing crates/geom/src/lib.rs:57-87 (number_past, called from svg_path at :49) Co-authored-by: Claude Haiku 5.5 --- crates/geom/src/lib.rs | 12 ++++++++++++ crates/geom/tests/svg_arc_flags.rs | 14 ++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 crates/geom/tests/svg_arc_flags.rs diff --git a/crates/geom/src/lib.rs b/crates/geom/src/lib.rs index c415f3b37..4bfbd97cd 100644 --- a/crates/geom/src/lib.rs +++ b/crates/geom/src/lib.rs @@ -63,7 +63,15 @@ fn number_past(d: &str, max: f64) -> bool { big } let (mut cur, mut dot, mut exp) = (String::new(), false, false); + // Whether the command is an arc, and how many numbers it has had: the 4th and 5th of each + // seven are flags, single `0`/`1` characters that may run into the next number unseparated. + let (mut arc, mut idx) = (false, 0usize); for c in d.chars() { + if cur.is_empty() && arc && matches!(idx % 7, 3 | 4) && matches!(c, '0' | '1') { + idx += 1; + (dot, exp) = (false, false); + continue; + } let continues = match c { '0'..='9' => true, '.' => !dot && !exp, @@ -77,9 +85,13 @@ fn number_past(d: &str, max: f64) -> bool { cur.push(c); continue; } + idx += cur.chars().any(|c| c.is_ascii_digit()) as usize; if big(&mut cur, max) { return true; } + if c.is_ascii_alphabetic() { + (arc, idx) = (matches!(c, 'A' | 'a'), 0); + } (dot, exp) = (c == '.', false); if matches!(c, '+' | '-' | '.') { cur.push(c); diff --git a/crates/geom/tests/svg_arc_flags.rs b/crates/geom/tests/svg_arc_flags.rs new file mode 100644 index 000000000..d5130dd69 --- /dev/null +++ b/crates/geom/tests/svg_arc_flags.rs @@ -0,0 +1,14 @@ +use figcraft_geom::svg_path; + +#[test] +fn compact_arc_flags_are_not_part_of_the_next_number() { + let compact = svg_path("M0 0A5 5 0 11999999999 0").expect("compact flags parse"); + let spaced = svg_path("M0 0A5 5 0 1 1 999999999 0").expect("spaced flags parse"); + assert_eq!(compact, spaced); +} + +#[test] +fn a_real_oversized_arc_coordinate_is_still_refused() { + assert!(svg_path("M0 0A5 5 0 112000000000 0").is_err()); + assert!(svg_path("M0 0A5 5 0 1 1 2000000000 0").is_err()); +}