Skip to content

Commit 500ed91

Browse files
committed
Zend: add consume_params support for fcall arguments
1 parent a83c025 commit 500ed91

File tree

8 files changed

+19
-1
lines changed

8 files changed

+19
-1
lines changed

Zend/zend_API.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,6 +1023,7 @@ static const char *zend_parse_arg_impl(zval *arg, va_list *va, const char **spec
10231023

10241024
if (check_null && Z_TYPE_P(arg) == IS_NULL) {
10251025
fci->size = 0;
1026+
fci->consume_params = 0;
10261027
fcc->function_handler = 0;
10271028
break;
10281029
}
@@ -4238,6 +4239,7 @@ ZEND_API zend_result zend_fcall_info_init(zval *callable, uint32_t check_flags,
42384239
fci->param_count = 0;
42394240
fci->params = NULL;
42404241
fci->named_params = NULL;
4242+
fci->consume_params = 0;
42414243

42424244
return SUCCESS;
42434245
}

Zend/zend_API.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ typedef struct _zend_fcall_info {
5454
* integrate APIs like call_user_func_array(). The usual restriction that
5555
* there may not be position arguments after named arguments applies. */
5656
HashTable *named_params;
57+
uint32_t consume_params;
5758
} zend_fcall_info;
5859

5960
typedef struct _zend_fcall_info_cache {
@@ -339,6 +340,7 @@ typedef struct _zend_fcall_info_cache {
339340

340341
#define ZEND_FCI_INITIALIZED(fci) ((fci).size != 0)
341342
#define ZEND_FCC_INITIALIZED(fcc) ((fcc).function_handler != NULL)
343+
#define ZEND_FCI_CONSUME_PARAM(arg_num) (1u << ((arg_num) - 1))
342344

343345
ZEND_API int zend_next_free_module(void);
344346

@@ -2486,6 +2488,7 @@ static zend_always_inline bool zend_parse_arg_func(zval *arg, zend_fcall_info *d
24862488
{
24872489
if (check_null && UNEXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
24882490
dest_fci->size = 0;
2491+
dest_fci->consume_params = 0;
24892492
dest_fcc->function_handler = NULL;
24902493
*error = NULL;
24912494
} else if (UNEXPECTED(zend_fcall_info_init(arg, 0, dest_fci, dest_fcc, NULL, error) != SUCCESS)) {

Zend/zend_closures.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ ZEND_METHOD(Closure, call)
155155
fci_cache.object = fci.object = newobj;
156156

157157
fci.size = sizeof(fci);
158+
fci.consume_params = 0;
158159
ZVAL_OBJ(&fci.function_name, &closure->std);
159160
ZVAL_UNDEF(&closure_result);
160161
fci.retval = &closure_result;

Zend/zend_exceptions.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,7 @@ ZEND_METHOD(Exception, __toString)
687687
fci.params = NULL;
688688
fci.object = NULL;
689689
fci.named_params = NULL;
690+
fci.consume_params = 0;
690691

691692
zend_fcall_info_cache fcc;
692693
fcc.function_handler = getTraceAsString;

Zend/zend_execute_API.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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;

Zend/zend_gc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1922,6 +1922,7 @@ static zend_fiber *gc_create_destructor_fiber(void)
19221922

19231923
fiber = (zend_fiber *)Z_OBJ(zobj);
19241924
fiber->fci.size = sizeof(fiber->fci);
1925+
fiber->fci.consume_params = 0;
19251926
fiber->fci_cache.function_handler = (zend_function*) &gc_destructor_fiber;
19261927

19271928
GC_G(dtor_fiber) = fiber;

ext/dom/xpath_callbacks.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,7 @@ static zend_result php_dom_xpath_callback_dispatch(php_dom_xpath_callbacks *xpat
408408
fci.param_count = param_count;
409409
fci.params = params;
410410
fci.named_params = NULL;
411+
fci.consume_params = 0;
411412
ZVAL_STRINGL(&fci.function_name, function_name, function_name_length);
412413

413414
zend_call_function(&fci, NULL);

ext/ffi/ffi.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,7 @@ static void zend_ffi_callback_trampoline(ffi_cif* cif, void* ret, void** args, v
950950
fci.object = NULL;
951951
fci.param_count = callback_data->arg_count;
952952
fci.named_params = NULL;
953+
fci.consume_params = 0;
953954

954955
if (callback_data->type->func.args) {
955956
int n = 0;

0 commit comments

Comments
 (0)