@@ -6,12 +6,12 @@ use std::ptr::null_mut;
66#[ derive( Debug ) ]
77pub struct CatchError ;
88
9- pub ( crate ) unsafe extern "C" fn panic_wrapper < R , F : Fn ( ) -> R + RefUnwindSafe > (
9+ pub ( crate ) unsafe extern "C" fn panic_wrapper < R , F : FnMut ( ) -> R + RefUnwindSafe > (
1010 ctx : * const c_void ,
1111) -> * const c_void {
1212 // we try to catch panic here so we correctly shutdown php if it happens
1313 // mandatory when we do assert on test as other test would not run correctly
14- let panic = catch_unwind ( || ( * ( ctx as * const F ) ) ( ) ) ;
14+ let panic = catch_unwind ( || ( * ( ctx as * mut F ) ) ( ) ) ;
1515
1616 Box :: into_raw ( Box :: new ( panic) ) as * mut c_void
1717}
@@ -26,7 +26,7 @@ pub(crate) unsafe extern "C" fn panic_wrapper<R, F: Fn() -> R + RefUnwindSafe>(
2626///
2727/// * `Ok(R)` - The result of the function
2828/// * `Err(CatchError)` - A bailout occurred during the execution
29- pub fn try_catch < R , F : Fn ( ) -> R + RefUnwindSafe > ( func : F ) -> Result < R , CatchError > {
29+ pub fn try_catch < R , F : FnMut ( ) -> R + RefUnwindSafe > ( func : F ) -> Result < R , CatchError > {
3030 let mut panic_ptr = null_mut ( ) ;
3131 let has_bailout = unsafe {
3232 ext_php_rs_zend_try_catch (
@@ -67,6 +67,7 @@ pub fn bailout() {
6767mod tests {
6868 use crate :: embed:: Embed ;
6969 use crate :: zend:: { bailout, try_catch} ;
70+ use std:: ptr:: null_mut;
7071
7172 #[ test]
7273 fn test_catch ( ) {
@@ -124,4 +125,21 @@ mod tests {
124125
125126 assert_eq ! ( foo, "foo" ) ;
126127 }
128+
129+ #[ test]
130+ fn test_memory_leak ( ) {
131+ let mut ptr = null_mut ( ) ;
132+
133+ let _ = try_catch ( || {
134+ let mut result = "foo" . to_string ( ) ;
135+ ptr = & mut result;
136+
137+ bailout ( ) ;
138+ } ) ;
139+
140+ // Check that the string is never released
141+ let result = unsafe { & * ptr as & str } ;
142+
143+ assert_eq ! ( result, "foo" ) ;
144+ }
127145}
0 commit comments