From d845ac27dbb263ff331277d5254c4109646f2f26 Mon Sep 17 00:00:00 2001 From: Hendrik Hamerlinck Date: Sun, 23 Nov 2025 12:39:22 +0100 Subject: [PATCH 1/2] fix: prevent crashes from SVG rendering --- tiny_skia/src/vector.rs | 17 +++++++++++++++-- wgpu/src/image/vector.rs | 17 +++++++++++++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/tiny_skia/src/vector.rs b/tiny_skia/src/vector.rs index ea7de215..d673df41 100644 --- a/tiny_skia/src/vector.rs +++ b/tiny_skia/src/vector.rs @@ -7,7 +7,7 @@ use tiny_skia::Transform; use std::cell::RefCell; use std::collections::hash_map; -use std::fs; +use std::{fs, panic}; use std::sync::Arc; #[derive(Debug)] @@ -168,7 +168,20 @@ impl Cache { tiny_skia::Transform::default() }; - resvg::render(tree, transform, &mut image.as_mut()); + // SVG rendering can panic on malformed or complex vectors. + // We catch panics to prevent crashes and continue gracefully. + let render_result = + panic::catch_unwind(panic::AssertUnwindSafe(|| { + resvg::render(tree, transform, &mut image.as_mut()); + })); + + if render_result.is_err() { + log::warn!( + "SVG rendering panicked for handle ID: {}", + handle.id() + ); + return None; + } if let Some([r, g, b, _]) = key.color { // Apply color filter diff --git a/wgpu/src/image/vector.rs b/wgpu/src/image/vector.rs index 31fb2fa6..882fb427 100644 --- a/wgpu/src/image/vector.rs +++ b/wgpu/src/image/vector.rs @@ -5,7 +5,7 @@ use crate::image::atlas::{self, Atlas}; use resvg::tiny_skia; use resvg::usvg; use rustc_hash::{FxHashMap, FxHashSet}; -use std::fs; +use std::{fs, panic}; use std::sync::Arc; /// Entry in cache corresponding to an svg handle @@ -154,7 +154,20 @@ impl Cache { tiny_skia::Transform::default() }; - resvg::render(tree, transform, &mut img.as_mut()); + // SVG rendering can panic on malformed or complex vectors. + // We catch panics to prevent crashes and continue gracefully. + let render_result = + panic::catch_unwind(panic::AssertUnwindSafe(|| { + resvg::render(tree, transform, &mut img.as_mut()); + })); + + if render_result.is_err() { + log::warn!( + "SVG rendering panicked for handle ID: {}", + handle.id() + ); + return None; + } let mut rgba = img.take(); From 4cc7eb47f7b444e3a1473c7993f505dbc4fc24bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Mon, 1 Dec 2025 17:01:40 +0100 Subject: [PATCH 2/2] Try to render corrupt SVGs after panic --- tiny_skia/src/vector.rs | 18 +++++++----------- wgpu/src/image/vector.rs | 11 +++++------ 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/tiny_skia/src/vector.rs b/tiny_skia/src/vector.rs index d673df41..827f2e99 100644 --- a/tiny_skia/src/vector.rs +++ b/tiny_skia/src/vector.rs @@ -7,7 +7,8 @@ use tiny_skia::Transform; use std::cell::RefCell; use std::collections::hash_map; -use std::{fs, panic}; +use std::fs; +use std::panic; use std::sync::Arc; #[derive(Debug)] @@ -170,17 +171,12 @@ impl Cache { // SVG rendering can panic on malformed or complex vectors. // We catch panics to prevent crashes and continue gracefully. - let render_result = - panic::catch_unwind(panic::AssertUnwindSafe(|| { - resvg::render(tree, transform, &mut image.as_mut()); - })); + let render = panic::catch_unwind(panic::AssertUnwindSafe(|| { + resvg::render(tree, transform, &mut image.as_mut()); + })); - if render_result.is_err() { - log::warn!( - "SVG rendering panicked for handle ID: {}", - handle.id() - ); - return None; + if let Err(error) = render { + log::warn!("SVG rendering for {handle:?} panicked: {error:?}"); } if let Some([r, g, b, _]) = key.color { diff --git a/wgpu/src/image/vector.rs b/wgpu/src/image/vector.rs index 882fb427..0704a966 100644 --- a/wgpu/src/image/vector.rs +++ b/wgpu/src/image/vector.rs @@ -5,7 +5,8 @@ use crate::image::atlas::{self, Atlas}; use resvg::tiny_skia; use resvg::usvg; use rustc_hash::{FxHashMap, FxHashSet}; -use std::{fs, panic}; +use std::fs; +use std::panic; use std::sync::Arc; /// Entry in cache corresponding to an svg handle @@ -156,17 +157,15 @@ impl Cache { // SVG rendering can panic on malformed or complex vectors. // We catch panics to prevent crashes and continue gracefully. - let render_result = + let render = panic::catch_unwind(panic::AssertUnwindSafe(|| { resvg::render(tree, transform, &mut img.as_mut()); })); - if render_result.is_err() { + if let Err(error) = render { log::warn!( - "SVG rendering panicked for handle ID: {}", - handle.id() + "SVG rendering for {handle:?} panicked: {error:?}" ); - return None; } let mut rgba = img.take();