--- /dev/null
+--TEST--
+Argument unpacking with many arguments
+--FILE--
+<?php
+
+function fn(...$args) {
+ var_dump(count($args));
+}
+
+$array = array_fill(0, 10000, 42);
+fn(...$array, ...$array);
+
+?>
+--EXPECT--
+int(20000)
}
/* }}} */
+static void **zend_vm_stack_push_args_with_copy(int count TSRMLS_DC) /* {{{ */
+{
+ zend_vm_stack p = EG(argument_stack);
+
+ zend_vm_stack_extend(count + 1 TSRMLS_CC);
+
+ EG(argument_stack)->top += count;
+ *(EG(argument_stack)->top) = (void*)(zend_uintptr_t)count;
+ while (count-- > 0) {
+ void *data = *(--p->top);
+
+ if (UNEXPECTED(p->top == ZEND_VM_STACK_ELEMETS(p))) {
+ zend_vm_stack r = p;
+
+ EG(argument_stack)->prev = p->prev;
+ p = p->prev;
+ efree(r);
+ }
+ *(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + count) = data;
+ }
+ return EG(argument_stack)->top++;
+}
+/* }}} */
+
+static zend_always_inline void** zend_vm_stack_push_args(int count TSRMLS_DC) /* {{{ */
+{
+ if (UNEXPECTED(EG(argument_stack)->top - ZEND_VM_STACK_ELEMETS(EG(argument_stack)) < count)
+ || UNEXPECTED(EG(argument_stack)->top == EG(argument_stack)->end)) {
+ return zend_vm_stack_push_args_with_copy(count TSRMLS_CC);
+ }
+ *(EG(argument_stack)->top) = (void*)(zend_uintptr_t)count;
+ return EG(argument_stack)->top++;
+}
+/* }}} */
+
+
#define ZEND_VM_NEXT_OPCODE() \
CHECK_SYMBOL_TABLES() \
ZEND_VM_INC_OPCODE(); \
}
num_args = opline->extended_value + EX(call)->num_additional_args;
- EX(function_state).arguments = zend_vm_stack_top(TSRMLS_C);
- zend_vm_stack_push((void*)(zend_uintptr_t) num_args TSRMLS_CC);
+ if (EX(call)->num_additional_args) {
+ EX(function_state).arguments = zend_vm_stack_push_args(num_args TSRMLS_CC);
+ } else {
+ EX(function_state).arguments = zend_vm_stack_top(TSRMLS_C);
+ zend_vm_stack_push((void*)(zend_uintptr_t) num_args TSRMLS_CC);
+ }
LOAD_OPLINE();
if (fbc->type == ZEND_INTERNAL_FUNCTION) {
}
num_args = opline->extended_value + EX(call)->num_additional_args;
- EX(function_state).arguments = zend_vm_stack_top(TSRMLS_C);
- zend_vm_stack_push((void*)(zend_uintptr_t) num_args TSRMLS_CC);
+ if (EX(call)->num_additional_args) {
+ EX(function_state).arguments = zend_vm_stack_push_args(num_args TSRMLS_CC);
+ } else {
+ EX(function_state).arguments = zend_vm_stack_top(TSRMLS_C);
+ zend_vm_stack_push((void*)(zend_uintptr_t) num_args TSRMLS_CC);
+ }
LOAD_OPLINE();
if (fbc->type == ZEND_INTERNAL_FUNCTION) {