From 4a393b45e17fe7b408e7b54dde2a92abbb389e0c Mon Sep 17 00:00:00 2001 From: Sai Asish Y Date: Tue, 12 May 2026 17:31:45 -0700 Subject: [PATCH] fix: handle non-finite values in f32_bound --- crates/resvg/src/filter/mod.rs | 8 ++++---- crates/usvg/src/parser/mod.rs | 8 ++++---- crates/usvg/tests/parser.rs | 10 ++++++++++ 3 files changed, 18 insertions(+), 8 deletions(-) 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 = "