@@ -6,12 +6,12 @@ use std::ptr::null_mut;
6
6
#[ derive( Debug ) ]
7
7
pub struct CatchError ;
8
8
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 > (
10
10
ctx : * const c_void ,
11
11
) -> * const c_void {
12
12
// we try to catch panic here so we correctly shutdown php if it happens
13
13
// 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 ) ) ( ) ) ;
15
15
16
16
Box :: into_raw ( Box :: new ( panic) ) as * mut c_void
17
17
}
@@ -26,7 +26,7 @@ pub(crate) unsafe extern "C" fn panic_wrapper<R, F: Fn() -> R + RefUnwindSafe>(
26
26
///
27
27
/// * `Ok(R)` - The result of the function
28
28
/// * `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 > {
30
30
let mut panic_ptr = null_mut ( ) ;
31
31
let has_bailout = unsafe {
32
32
ext_php_rs_zend_try_catch (
@@ -67,6 +67,7 @@ pub fn bailout() {
67
67
mod tests {
68
68
use crate :: embed:: Embed ;
69
69
use crate :: zend:: { bailout, try_catch} ;
70
+ use std:: ptr:: null_mut;
70
71
71
72
#[ test]
72
73
fn test_catch ( ) {
@@ -124,4 +125,21 @@ mod tests {
124
125
125
126
assert_eq ! ( foo, "foo" ) ;
126
127
}
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
+ }
127
145
}
0 commit comments