@@ -797,6 +797,7 @@ zend_result _call_user_function_impl(zval *object, zval *function_name, zval *re
797797 fci .param_count = param_count ;
798798 fci .params = params ;
799799 fci .named_params = named_params ;
800+ fci .consume_params = 0 ;
800801
801802 return zend_call_function (& fci , NULL );
802803}
@@ -869,6 +870,7 @@ zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_
869870 zval * param = ZEND_CALL_ARG (call , i + 1 );
870871 zval * arg = & fci -> params [i ];
871872 bool must_wrap = false;
873+ bool consume_arg = i < 32 && ((fci -> consume_params >> i ) & 1 );
872874 if (UNEXPECTED (Z_ISUNDEF_P (arg ))) {
873875 /* Allow forwarding undef slots. This is only used by Closure::__invoke(). */
874876 ZVAL_UNDEF (param );
@@ -905,7 +907,12 @@ zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_
905907 }
906908
907909 if (EXPECTED (!must_wrap )) {
908- ZVAL_COPY (param , arg );
910+ if (consume_arg && !Z_ISREF_P (arg ) && arg == & fci -> params [i ]) {
911+ ZVAL_COPY_VALUE (param , arg );
912+ ZVAL_UNDEF (arg );
913+ } else {
914+ ZVAL_COPY (param , arg );
915+ }
909916 } else {
910917 Z_TRY_ADDREF_P (arg );
911918 ZVAL_NEW_REF (param , arg );
@@ -1091,6 +1098,7 @@ ZEND_API void zend_call_known_function(
10911098 fci .param_count = param_count ;
10921099 fci .params = params ;
10931100 fci .named_params = named_params ;
1101+ fci .consume_params = 0 ;
10941102 ZVAL_UNDEF (& fci .function_name ); /* Unused */
10951103
10961104 fcic .function_handler = fn ;
0 commit comments