diff options
author | Nikita Popov <nikic@php.net> | 2013-08-29 11:35:11 +0200 |
---|---|---|
committer | Nikita Popov <nikic@php.net> | 2014-01-11 12:42:08 +0100 |
commit | 2c47dfbaebb203ab547f3c7e786cb1db5e84674a (patch) | |
tree | 0afe28b1bc1a9de0861b61bbbe9eeceb289edfde /Zend/zend_vm_execute.h | |
parent | c7bb28333804403c1e7cd817386ea1d527ad25e6 (diff) | |
download | php-git-2c47dfbaebb203ab547f3c7e786cb1db5e84674a.tar.gz |
Implement argument unpacking
RFC: https://wiki.php.net/rfc/argument_unpacking
Diffstat (limited to 'Zend/zend_vm_execute.h')
-rw-r--r-- | Zend/zend_vm_execute.h | 440 |
1 files changed, 363 insertions, 77 deletions
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index e9eda3e0a2..0651389f74 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -481,6 +481,7 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR USE_OPLINE zend_bool should_change_scope = 0; zend_function *fbc = EX(function_state).function; + zend_uint num_args; SAVE_OPLINE(); EX(object) = EX(call)->object; @@ -525,19 +526,18 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR EG(called_scope) = EX(call)->called_scope; } + 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)opline->extended_value TSRMLS_CC); + zend_vm_stack_push((void*)(zend_uintptr_t) num_args TSRMLS_CC); LOAD_OPLINE(); if (fbc->type == ZEND_INTERNAL_FUNCTION) { if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) { - zend_uint i=0; - zval **p = (zval**)EX(function_state).arguments; - ulong arg_count = opline->extended_value; + zend_uint i; + void **p = EX(function_state).arguments - num_args; - while (arg_count>0) { - zend_verify_arg_type(fbc, ++i, *(p-arg_count), 0 TSRMLS_CC); - arg_count--; + for (i = 0; i < num_args; ++i, ++p) { + zend_verify_arg_type(fbc, i + 1, (zval *) *p, 0 TSRMLS_CC); } } @@ -551,7 +551,7 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ - fbc->internal_function.handler(opline->extended_value, ret->var.ptr, &ret->var.ptr, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC); + fbc->internal_function.handler(num_args, ret->var.ptr, &ret->var.ptr, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC); } else { zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC); } @@ -601,7 +601,7 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR /* Not sure what should be done here if it's a static method */ if (EXPECTED(EX(object) != NULL)) { - Z_OBJ_HT_P(EX(object))->call_method(fbc->common.function_name, opline->extended_value, EX_T(opline->result.var).var.ptr, &EX_T(opline->result.var).var.ptr, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC); + Z_OBJ_HT_P(EX(object))->call_method(fbc->common.function_name, num_args, EX_T(opline->result.var).var.ptr, &EX_T(opline->result.var).var.ptr, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC); } else { zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object"); } @@ -701,6 +701,154 @@ static int ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER ZEND_VM_RETURN(); } +static int ZEND_FASTCALL ZEND_SEND_UNPACK_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *args; + int arg_num; + SAVE_OPLINE(); + + args = get_zval_ptr(opline->op1_type, &opline->op1, execute_data, &free_op1, BP_VAR_R); + arg_num = opline->op2.num + EX(call)->num_additional_args + 1; + + switch (Z_TYPE_P(args)) { + case IS_ARRAY: { + HashTable *ht = Z_ARRVAL_P(args); + HashPosition pos; + zval **arg_ptr, *arg; + + ZEND_VM_STACK_GROW_IF_NEEDED(zend_hash_num_elements(ht)); + + for (zend_hash_internal_pointer_reset_ex(ht, &pos); + zend_hash_get_current_data_ex(ht, (void **) &arg_ptr, &pos) == SUCCESS; + zend_hash_move_forward_ex(ht, &pos), ++arg_num + ) { + char *name; + zend_uint name_len; + zend_ulong index; + + if (zend_hash_get_current_key_ex(ht, &name, &name_len, &index, 0, &pos) == HASH_KEY_IS_STRING) { + zend_error(E_RECOVERABLE_ERROR, "Cannot unpack array with string keys"); + FREE_OP(free_op1); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } + + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, arg_num)) { + SEPARATE_ZVAL_TO_MAKE_IS_REF(arg_ptr); + arg = *arg_ptr; + Z_ADDREF_P(arg); + } else if (Z_ISREF_PP(arg_ptr)) { + ALLOC_ZVAL(arg); + MAKE_COPY_ZVAL(arg_ptr, arg); + } else { + arg = *arg_ptr; + Z_ADDREF_P(arg); + } + + zend_vm_stack_push(arg TSRMLS_CC); + EX(call)->num_additional_args++; + } + break; + } + case IS_OBJECT: { + zend_class_entry *ce = Z_OBJCE_P(args); + zend_object_iterator *iter; + + if (!ce || !ce->get_iterator) { + zend_error(E_WARNING, "Only arrays and Traversables can be unpacked"); + break; + } + + iter = ce->get_iterator(ce, args, 0 TSRMLS_CC); + if (UNEXPECTED(!iter)) { + FREE_OP(free_op1); + if (!EG(exception)) { + zend_throw_exception_ex( + NULL, 0 TSRMLS_CC, "Object of type %s did not create an Iterator", ce->name + ); + } + HANDLE_EXCEPTION(); + } + + if (iter->funcs->rewind) { + iter->funcs->rewind(iter TSRMLS_CC); + if (UNEXPECTED(EG(exception) != NULL)) { + goto unpack_iter_dtor; + } + } + + for (; iter->funcs->valid(iter TSRMLS_CC) == SUCCESS; ++arg_num) { + zval **arg_ptr, *arg; + + if (UNEXPECTED(EG(exception) != NULL)) { + goto unpack_iter_dtor; + } + + iter->funcs->get_current_data(iter, &arg_ptr TSRMLS_CC); + if (UNEXPECTED(EG(exception) != NULL)) { + goto unpack_iter_dtor; + } + + if (iter->funcs->get_current_key) { + zval key; + iter->funcs->get_current_key(iter, &key TSRMLS_CC); + if (UNEXPECTED(EG(exception) != NULL)) { + goto unpack_iter_dtor; + } + + if (Z_TYPE(key) == IS_STRING) { + zend_error(E_RECOVERABLE_ERROR, + "Cannot unpack Traversable with string keys"); + zval_dtor(&key); + goto unpack_iter_dtor; + } + + zval_dtor(&key); + } + + if (ARG_MUST_BE_SENT_BY_REF(EX(call)->fbc, arg_num)) { + zend_error( + E_WARNING, "Cannot pass by-reference argument %d of %s%s%s()" + " by unpacking a Traversable, passing by-value instead", arg_num, + EX(call)->fbc->common.scope ? EX(call)->fbc->common.scope->name : "", + EX(call)->fbc->common.scope ? "::" : "", + EX(call)->fbc->common.function_name + ); + } + + if (Z_ISREF_PP(arg_ptr)) { + ALLOC_ZVAL(arg); + MAKE_COPY_ZVAL(arg_ptr, arg); + } else { + arg = *arg_ptr; + Z_ADDREF_P(arg); + } + + ZEND_VM_STACK_GROW_IF_NEEDED(1); + zend_vm_stack_push(arg TSRMLS_CC); + EX(call)->num_additional_args++; + + iter->funcs->move_forward(iter TSRMLS_CC); + if (UNEXPECTED(EG(exception) != NULL)) { + goto unpack_iter_dtor; + } + } + +unpack_iter_dtor: + iter->funcs->dtor(iter TSRMLS_CC); + break; + } + default: + zend_error(E_WARNING, "Only arrays and Traversables can be unpacked"); + } + + FREE_OP(free_op1); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -814,6 +962,7 @@ static int ZEND_FASTCALL ZEND_NEW_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) call->fbc = constructor; call->object = object_zval; call->called_scope = EX_T(opline->op1.var).class_entry; + call->num_additional_args = 0; call->is_ctor_call = 1; call->is_ctor_result_used = RETURN_VALUE_USED(opline); EX(call) = call; @@ -1285,10 +1434,13 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE } else { CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } + call->object = NULL; call->called_scope = NULL; + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; + /*CHECK_EXCEPTION();*/ ZEND_VM_NEXT_OPCODE(); } else { @@ -1315,8 +1467,10 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE call->object = NULL; call->called_scope = NULL; + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else if (IS_CONST != IS_CONST && IS_CONST != IS_TMP_VAR && @@ -1333,8 +1487,11 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE } else { } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else if (IS_CONST != IS_CONST && @@ -1400,6 +1557,8 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, Z_STRVAL_PP(method)); } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -1439,7 +1598,9 @@ static int ZEND_FASTCALL ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPC call->object = NULL; call->called_scope = NULL; + call->num_additional_args = 0; call->is_ctor_call = 0; + EX(call) = call; ZEND_VM_NEXT_OPCODE(); } @@ -1609,10 +1770,13 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H } else { CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } + call->object = NULL; call->called_scope = NULL; + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; + /*CHECK_EXCEPTION();*/ ZEND_VM_NEXT_OPCODE(); } else { @@ -1637,10 +1801,13 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H } efree(lcname); zval_dtor(free_op2.var); + call->object = NULL; call->called_scope = NULL; + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else if (IS_TMP_VAR != IS_CONST && IS_TMP_VAR != IS_TMP_VAR && @@ -1657,8 +1824,11 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H } else { zval_dtor(free_op2.var); } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else if (IS_TMP_VAR != IS_CONST && @@ -1724,8 +1894,11 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, Z_STRVAL_PP(method)); } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; + zval_dtor(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -1796,10 +1969,13 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H } else { CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } + call->object = NULL; call->called_scope = NULL; + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; + /*CHECK_EXCEPTION();*/ ZEND_VM_NEXT_OPCODE(); } else { @@ -1824,10 +2000,13 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H } efree(lcname); zval_ptr_dtor_nogc(&free_op2.var); + call->object = NULL; call->called_scope = NULL; + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else if (IS_VAR != IS_CONST && IS_VAR != IS_TMP_VAR && @@ -1844,8 +2023,11 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H } else { zval_ptr_dtor_nogc(&free_op2.var); } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else if (IS_VAR != IS_CONST && @@ -1911,8 +2093,11 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, Z_STRVAL_PP(method)); } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; + zval_ptr_dtor_nogc(&free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -2021,10 +2206,13 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA } else { CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } + call->object = NULL; call->called_scope = NULL; + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; + /*CHECK_EXCEPTION();*/ ZEND_VM_NEXT_OPCODE(); } else { @@ -2051,8 +2239,10 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA call->object = NULL; call->called_scope = NULL; + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else if (IS_CV != IS_CONST && IS_CV != IS_TMP_VAR && @@ -2069,8 +2259,11 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA } else { } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else if (IS_CV != IS_CONST && @@ -2136,6 +2329,8 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, Z_STRVAL_PP(method)); } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -2375,9 +2570,11 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A } else { CACHE_PTR(opline->op1.literal->cache_slot, EX(function_state).function); } + call->fbc = EX(function_state).function; call->object = NULL; call->called_scope = NULL; + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -2534,10 +2731,13 @@ static int ZEND_FASTCALL ZEND_SEND_VAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A USE_OPLINE SAVE_OPLINE(); - if (opline->extended_value==ZEND_DO_FCALL_BY_NAME - && ARG_MUST_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { - zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.opline_num); + if (opline->extended_value == ZEND_DO_FCALL_BY_NAME) { + int arg_num = opline->op2.num + EX(call)->num_additional_args; + if (ARG_MUST_BE_SENT_BY_REF(EX(call)->fbc, arg_num)) { + zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", arg_num); + } } + { zval *valptr; zval *value; @@ -3542,7 +3742,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_OPCO { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_CONST_CONST(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_CONST_CONST(zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC) ? BP_VAR_W : BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -3712,6 +3912,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER( call->called_scope = Z_OBJCE_P(call->object); } } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -4695,6 +4897,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE call->called_scope = Z_OBJCE_P(call->object); } } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -5396,7 +5600,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_CONST_VAR(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_CONST_VAR(zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC) ? BP_VAR_W : BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -5542,6 +5746,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE call->called_scope = Z_OBJCE_P(call->object); } } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -6131,7 +6337,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER(ZEND_OPC { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC) ? BP_VAR_W : BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -6260,6 +6466,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER call->called_scope = Z_OBJCE_P(call->object); } } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -7111,6 +7319,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN call->called_scope = Z_OBJCE_P(call->object); } } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -7819,10 +8029,13 @@ static int ZEND_FASTCALL ZEND_SEND_VAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG USE_OPLINE SAVE_OPLINE(); - if (opline->extended_value==ZEND_DO_FCALL_BY_NAME - && ARG_MUST_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { - zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.opline_num); + if (opline->extended_value == ZEND_DO_FCALL_BY_NAME) { + int arg_num = opline->op2.num + EX(call)->num_additional_args; + if (ARG_MUST_BE_SENT_BY_REF(EX(call)->fbc, arg_num)) { + zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", arg_num); + } } + { zval *valptr; zval *value; @@ -8880,7 +9093,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_TMP_CONST(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_TMP_CONST(zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC) ? BP_VAR_W : BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -9051,6 +9264,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCO call->object = this_ptr; } } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -9899,6 +10114,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE call->object = this_ptr; } } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -10602,7 +10819,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_H { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_TMP_VAR(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_TMP_VAR(zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC) ? BP_VAR_W : BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -10748,6 +10965,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE call->object = this_ptr; } } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -11339,7 +11558,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCOD { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_TMP_UNUSED(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_TMP_UNUSED(zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC) ? BP_VAR_W : BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12177,6 +12396,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_ call->object = this_ptr; } } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -13040,14 +13261,18 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND USE_OPLINE zend_free_op free_op1; zval *varptr; + int arg_num; SAVE_OPLINE(); if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) { /* Had function_ptr at compile_time */ if (!(opline->extended_value & ZEND_ARG_SEND_BY_REF)) { return zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - } else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { - return zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else { + arg_num = opline->op2.num + EX(call)->num_additional_args; + if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, arg_num)) { + return zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } } varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); @@ -13065,7 +13290,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ? !(opline->extended_value & ZEND_ARG_SEND_SILENT) : - !ARG_MAY_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { + !ARG_MAY_BE_SENT_BY_REF(EX(call)->fbc, arg_num)) { zend_error(E_STRICT, "Only variables should be passed by reference"); } ALLOC_ZVAL(valptr); @@ -13102,9 +13327,11 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG } if (opline->extended_value == ZEND_DO_FCALL_BY_NAME && - EX(function_state).function->type == ZEND_INTERNAL_FUNCTION && - !ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { - return zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) { + int arg_num = opline->op2.num + EX(call)->num_additional_args; + if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, arg_num)) { + return zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } } SEPARATE_ZVAL_TO_MAKE_IS_REF(varptr_ptr); @@ -13121,9 +13348,11 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG { USE_OPLINE - if ((opline->extended_value == ZEND_DO_FCALL_BY_NAME) - && ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { - return ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + if (opline->extended_value == ZEND_DO_FCALL_BY_NAME) { + int arg_num = opline->op2.num + EX(call)->num_additional_args; + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, arg_num)) { + return ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } } SAVE_OPLINE(); return zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -14738,7 +14967,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_VAR_CONST(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_VAR_CONST(zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC) ? BP_VAR_W : BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -14846,9 +15075,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OP SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { zval **container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } @@ -15083,7 +15311,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OP { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1; zval *property; @@ -15395,6 +15623,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCO call->object = this_ptr; } } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -15520,6 +15750,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE call->called_scope = Z_OBJCE_P(call->object); } } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -17169,9 +17401,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCO SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { zval **container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } @@ -17406,7 +17637,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCO { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1, free_op2; zval *property; @@ -17719,6 +17950,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE call->object = this_ptr; } } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -17845,6 +18078,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND call->called_scope = Z_OBJCE_P(call->object); } } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -19290,7 +19525,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_H { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_VAR_VAR(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_VAR_VAR(zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC) ? BP_VAR_W : BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -19398,9 +19633,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCO SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { zval **container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } @@ -19635,7 +19869,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCO { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1, free_op2; zval *property; @@ -20003,6 +20237,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE call->object = this_ptr; } } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -20129,6 +20365,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND call->called_scope = Z_OBJCE_P(call->object); } } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -21255,7 +21493,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCOD { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_VAR_UNUSED(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_VAR_UNUSED(zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC) ? BP_VAR_W : BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -21331,9 +21569,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_O SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { zval **container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } @@ -21554,6 +21791,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z call->called_scope = Z_OBJCE_P(call->object); } } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -22829,9 +23068,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCOD SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { zval **container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } @@ -23066,7 +23304,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCOD { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1; zval *property; @@ -23431,6 +23669,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_ call->object = this_ptr; } } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -23556,6 +23796,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_ call->called_scope = Z_OBJCE_P(call->object); } } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -24827,7 +25069,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER(ZEND { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1; zval *property; @@ -25049,6 +25291,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O call->object = this_ptr; } } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -26230,7 +26474,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMP_HANDLER(ZEND_O { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1, free_op2; zval *property; @@ -26451,6 +26695,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC call->object = this_ptr; } } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -27537,7 +27783,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_VAR_HANDLER(ZEND_O { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1, free_op2; zval *property; @@ -27758,6 +28004,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPC call->object = this_ptr; } } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -29268,7 +29516,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CV_HANDLER(ZEND_OP { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1; zval *property; @@ -29488,6 +29736,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO call->object = this_ptr; } } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -30516,14 +30766,18 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL USE_OPLINE zval *varptr; + int arg_num; SAVE_OPLINE(); if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) { /* Had function_ptr at compile_time */ if (!(opline->extended_value & ZEND_ARG_SEND_BY_REF)) { return zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - } else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { - return zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else { + arg_num = opline->op2.num + EX(call)->num_additional_args; + if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, arg_num)) { + return zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } } varptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); @@ -30541,7 +30795,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ? !(opline->extended_value & ZEND_ARG_SEND_SILENT) : - !ARG_MAY_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { + !ARG_MAY_BE_SENT_BY_REF(EX(call)->fbc, arg_num)) { zend_error(E_STRICT, "Only variables should be passed by reference"); } ALLOC_ZVAL(valptr); @@ -30578,9 +30832,11 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS } if (opline->extended_value == ZEND_DO_FCALL_BY_NAME && - EX(function_state).function->type == ZEND_INTERNAL_FUNCTION && - !ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { - return zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) { + int arg_num = opline->op2.num + EX(call)->num_additional_args; + if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, arg_num)) { + return zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } } SEPARATE_ZVAL_TO_MAKE_IS_REF(varptr_ptr); @@ -30596,9 +30852,11 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS { USE_OPLINE - if ((opline->extended_value == ZEND_DO_FCALL_BY_NAME) - && ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { - return ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + if (opline->extended_value == ZEND_DO_FCALL_BY_NAME) { + int arg_num = opline->op2.num + EX(call)->num_additional_args; + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, arg_num)) { + return ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } } SAVE_OPLINE(); return zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -32067,7 +32325,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_ { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_CV_CONST(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_CV_CONST(zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC) ? BP_VAR_W : BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -32174,9 +32432,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPC SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { zval **container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } @@ -32408,7 +32665,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPC { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1; zval *property; @@ -32717,6 +32974,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD call->object = this_ptr; } } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -34264,9 +34523,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCOD SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { zval **container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } @@ -34498,7 +34756,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCOD { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1, free_op2; zval *property; @@ -34808,6 +35066,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_ call->object = this_ptr; } } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -36249,7 +36509,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HA { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_CV_VAR(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_CV_VAR(zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC) ? BP_VAR_W : BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -36356,9 +36616,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCOD SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { zval **container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } @@ -36590,7 +36849,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCOD { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1, free_op2; zval *property; @@ -36954,6 +37213,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_ call->object = this_ptr; } } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -38076,7 +38337,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_CV_UNUSED(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_CV_UNUSED(zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC) ? BP_VAR_W : BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -38151,9 +38412,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OP SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { zval **container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } @@ -39502,9 +39762,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { zval **container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } @@ -39736,7 +39995,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1; zval *property; @@ -40097,6 +40356,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H call->object = this_ptr; } } + + call->num_additional_args = 0; call->is_ctor_call = 0; EX(call) = call; @@ -44788,6 +45049,31 @@ void zend_init_opcodes_handlers(void) ZEND_RECV_VARIADIC_SPEC_HANDLER, ZEND_RECV_VARIADIC_SPEC_HANDLER, ZEND_RECV_VARIADIC_SPEC_HANDLER, + ZEND_SEND_UNPACK_SPEC_HANDLER, + ZEND_SEND_UNPACK_SPEC_HANDLER, + ZEND_SEND_UNPACK_SPEC_HANDLER, + ZEND_SEND_UNPACK_SPEC_HANDLER, + ZEND_SEND_UNPACK_SPEC_HANDLER, + ZEND_SEND_UNPACK_SPEC_HANDLER, + ZEND_SEND_UNPACK_SPEC_HANDLER, + ZEND_SEND_UNPACK_SPEC_HANDLER, + ZEND_SEND_UNPACK_SPEC_HANDLER, + ZEND_SEND_UNPACK_SPEC_HANDLER, + ZEND_SEND_UNPACK_SPEC_HANDLER, + ZEND_SEND_UNPACK_SPEC_HANDLER, + ZEND_SEND_UNPACK_SPEC_HANDLER, + ZEND_SEND_UNPACK_SPEC_HANDLER, + ZEND_SEND_UNPACK_SPEC_HANDLER, + ZEND_SEND_UNPACK_SPEC_HANDLER, + ZEND_SEND_UNPACK_SPEC_HANDLER, + ZEND_SEND_UNPACK_SPEC_HANDLER, + ZEND_SEND_UNPACK_SPEC_HANDLER, + ZEND_SEND_UNPACK_SPEC_HANDLER, + ZEND_SEND_UNPACK_SPEC_HANDLER, + ZEND_SEND_UNPACK_SPEC_HANDLER, + ZEND_SEND_UNPACK_SPEC_HANDLER, + ZEND_SEND_UNPACK_SPEC_HANDLER, + ZEND_SEND_UNPACK_SPEC_HANDLER, ZEND_NULL_HANDLER }; zend_opcode_handlers = (opcode_handler_t*)labels; |