mirror of
https://github.com/storytold/wordcraft.git
synced 2026-11-09 20:22:17 +00:00
fix(geom): reject measurements that overflow to infinity in parse_measure (#1359)
This commit is contained in:
1 parent
159b84f54c
commit
ad485db499
1 file changed
+31
-1
+31
-1
@@ -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\"");
|
||||
|
||||
Reference in new issue
Block a user