@@ -743,15 +743,15 @@ static zend_always_inline bool zend_fcc_equals(const zend_fcall_info_cache* a, c
743
743
static zend_always_inline void zend_fcc_addref (zend_fcall_info_cache * fcc )
744
744
{
745
745
ZEND_ASSERT (ZEND_FCC_INITIALIZED (* fcc ) && "FCC Not initialized, possibly refetch trampoline freed by ZPP?" );
746
- /*
746
+ /* If the cached trampoline is set, free it */
747
747
if (UNEXPECTED (fcc -> function_handler == & EG (trampoline ))) {
748
- zend_function *copy = emalloc(sizeof(zend_function));
748
+ zend_function * copy = ( zend_function * ) emalloc (sizeof (zend_function ));
749
749
750
750
memcpy (copy , fcc -> function_handler , sizeof (zend_function ));
751
751
fcc -> function_handler -> common .function_name = NULL ;
752
752
fcc -> function_handler = copy ;
753
+ memset (& EG (trampoline ), 0 , sizeof (zend_function ));
753
754
}
754
- */
755
755
if (fcc -> object ) {
756
756
GC_ADDREF (fcc -> object );
757
757
}
@@ -768,13 +768,15 @@ static zend_always_inline void zend_fcc_dup(/* restrict */ zend_fcall_info_cache
768
768
769
769
static zend_always_inline void zend_fcc_dtor (zend_fcall_info_cache * fcc )
770
770
{
771
+ ZEND_ASSERT (fcc -> function_handler );
771
772
if (fcc -> object ) {
772
773
OBJ_RELEASE (fcc -> object );
773
774
}
775
+ /* Need to free potential trampoline (__call/__callStatic) copied function handler before releasing the closure */
776
+ zend_release_fcall_info_cache (fcc );
774
777
if (fcc -> closure ) {
775
778
OBJ_RELEASE (fcc -> closure );
776
779
}
777
- zend_release_fcall_info_cache (fcc );
778
780
memcpy (fcc , & empty_fcall_info_cache , sizeof (zend_fcall_info_cache ));
779
781
}
780
782
0 commit comments