fix(geom): reject measurements that overflow to infinity in parse_measure (#1359)

This commit is contained in:
Saad Abdullah committed 2026-10-13 16:46:36 +00:00
1 parent 159b84f54c
commit ad485db499
1 file changed
+31 -1
+31 -1
View File
@@ -124,7 +124,11 @@ pub fn parse_measure(s: &str, default: Unit) -> Option<f32> {
"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\"");