diff --git a/crates/color/src/lib.rs b/crates/color/src/lib.rs index 42fb6a69c..c2c0d06ed 100644 --- a/crates/color/src/lib.rs +++ b/crates/color/src/lib.rs @@ -180,6 +180,9 @@ impl Color { let h = parts.first()?.trim_end_matches("deg").parse::().ok()?; let s = parts.get(1)?.trim_end_matches('%').parse::().ok()? / 100.0; let l = parts.get(2)?.trim_end_matches('%').parse::().ok()? / 100.0; + if !(h.is_finite() && s.is_finite() && l.is_finite()) { + return None; + } let alpha = match parts.get(3) { Some(a) => parse_alpha(a)?, None => 1.0, @@ -286,7 +289,8 @@ fn css_hue(p: &str) -> Option { } fn parse_alpha(a: &str) -> Option { - if let Some(pc) = a.strip_suffix('%') { pc.parse::().ok().map(|v| v / 100.0) } else { a.parse::().ok() } + let v = if let Some(pc) = a.strip_suffix('%') { pc.parse::().ok().map(|v| v / 100.0) } else { a.parse::().ok() }?; + v.is_finite().then_some(v) } /// One colour stop of a gradient. diff --git a/crates/color/src/tests.rs b/crates/color/src/tests.rs index 2b628b714..03e4d1675 100644 --- a/crates/color/src/tests.rs +++ b/crates/color/src/tests.rs @@ -141,3 +141,10 @@ fn to_css_round_trips_every_alpha() { assert_eq!(Color::parse_css(&c.to_css()).unwrap().to_rgba8(), c.to_rgba8(), "alpha {a}: {}", c.to_css()); } } + +#[test] +fn css_hsl_rejects_non_finite() { + for s in ["hsl(nan,50%,50%)", "hsl(inf,50%,50%)", "hsl(0,inf%,50%)", "hsl(0,50%,infinity%)", "hsla(120,50%,50%,nan)"] { + assert_eq!(Color::parse_css(s), None, "{s}"); + } +}