diff --git a/crates/resvg/src/filter/mod.rs b/crates/resvg/src/filter/mod.rs index 36c56a5df..29ff3a7a4 100644 --- a/crates/resvg/src/filter/mod.rs +++ b/crates/resvg/src/filter/mod.rs @@ -241,15 +241,15 @@ fn from_linear_rgb(data: &mut [RGBA8]) { #[inline] fn f32_bound(min: f32, val: f32, max: f32) -> f32 { debug_assert!(min.is_finite()); - debug_assert!(val.is_finite()); debug_assert!(max.is_finite()); if val > max { max - } else if val < min { - min - } else { + } else if val >= min { val + } else { + // Catches `val < min` as well as a NaN `val`. + min } } diff --git a/crates/usvg/src/parser/mod.rs b/crates/usvg/src/parser/mod.rs index b3fbccdd6..004b1d3f8 100644 --- a/crates/usvg/src/parser/mod.rs +++ b/crates/usvg/src/parser/mod.rs @@ -177,14 +177,14 @@ pub fn decompress_svgz(data: &[u8]) -> Result, Error> { #[inline] pub(crate) fn f32_bound(min: f32, val: f32, max: f32) -> f32 { debug_assert!(min.is_finite()); - debug_assert!(val.is_finite()); debug_assert!(max.is_finite()); if val > max { max - } else if val < min { - min - } else { + } else if val >= min { val + } else { + // Catches `val < min` as well as a NaN `val`. + min } } diff --git a/crates/usvg/tests/parser.rs b/crates/usvg/tests/parser.rs index d1172fa69..905bbc0db 100644 --- a/crates/usvg/tests/parser.rs +++ b/crates/usvg/tests/parser.rs @@ -4,6 +4,16 @@ use tiny_skia_path::Rect; use usvg::Color; +#[test] +fn gradient_stop_offset_overflowing_f32() { + // `4e38` overflows f32 to infinity; parsing must not panic. + let svg = "\ + \ + \ + "; + assert!(usvg::Tree::from_str(svg, &usvg::Options::default()).is_ok()); +} + #[test] fn clippath_with_invalid_child() { let svg = "