diff --git a/Zend/tests/unpack_iterator_by_ref_type_check.phpt b/Zend/tests/unpack_iterator_by_ref_type_check.phpt new file mode 100644 index 00000000000..2fef31056bd --- /dev/null +++ b/Zend/tests/unpack_iterator_by_ref_type_check.phpt @@ -0,0 +1,18 @@ +--TEST-- +Unpack iterator by reference with type check +--FILE-- +getMessage(), "\n"; +} +?> +--EXPECTF-- +Warning: Cannot pass by-reference argument 1 of test() by unpacking a Traversable, passing by-value instead in %s on line %d +test(): Argument #1 ($a) must be of type T, null given, called in %s on line %d diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index f324d801c01..d28628c044a 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5126,6 +5126,9 @@ ZEND_VM_C_LABEL(send_again): break; } + ZVAL_DEREF(arg); + Z_TRY_ADDREF_P(arg); + if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { zend_error( E_WARNING, "Cannot pass by-reference argument %d of %s%s%s()" @@ -5134,9 +5137,11 @@ ZEND_VM_C_LABEL(send_again): EX(call)->func->common.scope ? "::" : "", ZSTR_VAL(EX(call)->func->common.function_name) ); + ZVAL_NEW_REF(top, arg); + } else { + ZVAL_COPY_VALUE(top, arg); } - ZVAL_COPY_DEREF(top, arg); zend_string_release(name); } else { if (have_named_params) { @@ -5145,6 +5150,11 @@ ZEND_VM_C_LABEL(send_again): break; } + zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, 1); + top = ZEND_CALL_ARG(EX(call), arg_num); + ZVAL_DEREF(arg); + Z_TRY_ADDREF_P(arg); + if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { zend_error( E_WARNING, "Cannot pass by-reference argument %d of %s%s%s()" @@ -5153,12 +5163,11 @@ ZEND_VM_C_LABEL(send_again): EX(call)->func->common.scope ? "::" : "", ZSTR_VAL(EX(call)->func->common.function_name) ); + ZVAL_NEW_REF(top, arg); + } else { + ZVAL_COPY_VALUE(top, arg); } - - zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, 1); - top = ZEND_CALL_ARG(EX(call), arg_num); - ZVAL_COPY_DEREF(top, arg); ZEND_CALL_NUM_ARGS(EX(call))++; } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index a4a268d81e8..329fa827dd4 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2248,6 +2248,9 @@ send_again: break; } + ZVAL_DEREF(arg); + Z_TRY_ADDREF_P(arg); + if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { zend_error( E_WARNING, "Cannot pass by-reference argument %d of %s%s%s()" @@ -2256,9 +2259,11 @@ send_again: EX(call)->func->common.scope ? "::" : "", ZSTR_VAL(EX(call)->func->common.function_name) ); + ZVAL_NEW_REF(top, arg); + } else { + ZVAL_COPY_VALUE(top, arg); } - ZVAL_COPY_DEREF(top, arg); zend_string_release(name); } else { if (have_named_params) { @@ -2267,6 +2272,11 @@ send_again: break; } + zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, 1); + top = ZEND_CALL_ARG(EX(call), arg_num); + ZVAL_DEREF(arg); + Z_TRY_ADDREF_P(arg); + if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { zend_error( E_WARNING, "Cannot pass by-reference argument %d of %s%s%s()" @@ -2275,12 +2285,11 @@ send_again: EX(call)->func->common.scope ? "::" : "", ZSTR_VAL(EX(call)->func->common.function_name) ); + ZVAL_NEW_REF(top, arg); + } else { + ZVAL_COPY_VALUE(top, arg); } - - zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, 1); - top = ZEND_CALL_ARG(EX(call), arg_num); - ZVAL_COPY_DEREF(top, arg); ZEND_CALL_NUM_ARGS(EX(call))++; }