From 002f8bec1476a00d7a259618fae6753a5307122c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 24 Mar 2025 16:03:20 +0200 Subject: [PATCH] typefind: Catch panics when calling typefind functions Otherwise a panic during typefinding will abort the process. Part-of: --- gstreamer/src/typefind.rs | 110 +++++++++++++++++++++++++++++++++++--- 1 file changed, 104 insertions(+), 6 deletions(-) diff --git a/gstreamer/src/typefind.rs b/gstreamer/src/typefind.rs index 803f594f9..3ac4c1737 100644 --- a/gstreamer/src/typefind.rs +++ b/gstreamer/src/typefind.rs @@ -115,7 +115,29 @@ unsafe extern "C" fn type_find_trampoline() + .copied() + .or_else(|| err.downcast_ref::().map(|s| s.as_str())); + if let Some(cause) = cause { + crate::error!( + crate::CAT_RUST, + "Failed to call typefind function due to panic: {}", + cause + ); + } else { + crate::error!( + crate::CAT_RUST, + "Failed to call typefind function due to panic" + ); + } + } } unsafe extern "C" fn type_find_closure_drop( @@ -130,9 +152,36 @@ unsafe extern "C" fn type_find_peek( size: u32, ) -> *const u8 { let find = &mut *(data as *mut &mut T); - match find.peek(offset, size) { - None => ptr::null(), - Some(data) => data.as_ptr(), + + let panic_result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + match find.peek(offset, size) { + None => ptr::null(), + Some(data) => data.as_ptr(), + } + })); + + match panic_result { + Ok(res) => res, + Err(err) => { + let cause = err + .downcast_ref::<&str>() + .copied() + .or_else(|| err.downcast_ref::().map(|s| s.as_str())); + if let Some(cause) = cause { + crate::error!( + crate::CAT_RUST, + "Failed to call typefind peek function due to panic: {}", + cause + ); + } else { + crate::error!( + crate::CAT_RUST, + "Failed to call typefind peek function due to panic" + ); + } + + ptr::null() + } } } @@ -142,14 +191,63 @@ unsafe extern "C" fn type_find_suggest( caps: *mut ffi::GstCaps, ) { let find = &mut *(data as *mut &mut T); - find.suggest(from_glib(probability as i32), &from_glib_borrow(caps)); + + let panic_result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + find.suggest(from_glib(probability as i32), &from_glib_borrow(caps)); + })); + + if let Err(err) = panic_result { + let cause = err + .downcast_ref::<&str>() + .copied() + .or_else(|| err.downcast_ref::().map(|s| s.as_str())); + if let Some(cause) = cause { + crate::error!( + crate::CAT_RUST, + "Failed to call typefind suggest function due to panic: {}", + cause + ); + } else { + crate::error!( + crate::CAT_RUST, + "Failed to call typefind suggest function due to panic" + ); + } + } } unsafe extern "C" fn type_find_get_length( data: glib::ffi::gpointer, ) -> u64 { let find = &*(data as *mut &mut T); - find.length().unwrap_or(u64::MAX) + + let panic_result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + find.length().unwrap_or(u64::MAX) + })); + + match panic_result { + Ok(res) => res, + Err(err) => { + let cause = err + .downcast_ref::<&str>() + .copied() + .or_else(|| err.downcast_ref::().map(|s| s.as_str())); + if let Some(cause) = cause { + crate::error!( + crate::CAT_RUST, + "Failed to call typefind length function due to panic: {}", + cause + ); + } else { + crate::error!( + crate::CAT_RUST, + "Failed to call typefind length function due to panic" + ); + } + + u64::MAX + } + } } #[derive(Debug)]