From ad485db499c25292cd0be0bbfa87c3c5974e29c6 Mon Sep 17 00:00:00 2001 From: Saad Abdullah Date: Tue, 13 Oct 2026 16:46:36 +0000 Subject: [PATCH] fix(geom): reject measurements that overflow to infinity in parse_measure (#1359) --- crates/geom/src/lib.rs | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/crates/geom/src/lib.rs b/crates/geom/src/lib.rs index 8f24ff426..16ce35776 100644 --- a/crates/geom/src/lib.rs +++ b/crates/geom/src/lib.rs @@ -124,7 +124,11 @@ pub fn parse_measure(s: &str, default: Unit) -> Option { "px" => 0.75, _ => return None, }; - Some(v * k) + // `v` is finite, but scaling it can still overflow to infinity (a + // near-`f32::MAX` value in inches, centimetres, picas or lines); reject + // those instead of returning an infinite measurement (#1359). + let pt = v * k; + if pt.is_finite() { Some(pt) } else { None } } /// A point in page space (points, y down). @@ -326,6 +330,32 @@ mod tests { assert_eq!(parse_measure("1,2,3", Unit::Inches), None); } + #[test] + fn parse_measure_rejects_overflow_to_infinity() { + // Finite inputs whose scaled result overflows `f32` must be rejected, + // never returned as an infinite measurement (#1359). + let e38 = "100000000000000000000000000000000000000"; // 1e38, finite + for s in [ + format!("{e38}\""), + format!("{e38} in"), + format!("{e38} cm"), + format!("{e38} pi"), + format!("{e38} li"), + format!("-{e38} in"), + e38.to_string(), // bare number in the default unit (inches below) + ] { + assert_eq!(parse_measure(&s, Unit::Inches), None, "input: {s}"); + } + // Millimetres scale by ~2.83, so 2e38 is needed to overflow. + let two_e38 = "200000000000000000000000000000000000000"; + assert_eq!(parse_measure(&format!("{two_e38} mm"), Unit::Inches), None); + // A large result that stays finite is still accepted, and points + // scale by 1, so a finite input in points stays finite. + let big = parse_measure("1000000000000000000000000000000 in", Unit::Points).unwrap(); + assert!(big.is_finite() && big > 0.0); + assert!(parse_measure(&format!("{e38} pt"), Unit::Inches).unwrap().is_finite()); + } + #[test] fn formats_measurements() { assert_eq!(Unit::Inches.format(72.0), "1\"");