com php-src: Merge branch 'PHP-5.4' into PHP-5.5: Zend/zend_v m_def.h Zend/zend_vm_execute.h
| From: | Dmitry Stogov | Date: | Mon, 25 Mar 2013 11:47:45 +0000 |
| Subject: | com php-src: Merge branch 'PHP-5.4' into PHP-5.5: Zend/zend_v m_def.h Zend/zend_vm_execute.h | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-71743@lists.php.net to get a copy of this message | ||
Commit: 96e5f5eb05af913f8a9b9297393f153c561bf51b
Author: Dmitry Stogov <dmitry@zend.com> Mon, 25 Mar 2013 15:47:45 +0400
Parents: 6a7088fd187f071df47fa09c6e215c916bfd699c e9f996c00d5cb6448dac1457dd9dae320c16904f
Branches: PHP-5.5 master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=96e5f5eb05af913f8a9b9297393f153c561bf51b
Log:
Merge branch 'PHP-5.4' into PHP-5.5
* PHP-5.4:
Fixed bug #63914 (zend_do_fcall_common_helper_SPEC does not handle exceptions properly). (Jeff
Welch)
Conflicts:
NEWS
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
Bugs:
https://bugs.php.net/63914
Changed paths:
MM Zend/zend_vm_def.h
MM Zend/zend_vm_execute.h
diff --cc Zend/zend_vm_def.h index 206a233,ffa94a1..31a5fac --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@@ -1829,266 -1819,6 +1829,268 @@@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VA ZEND_VM_NEXT_OPCODE(); } +ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) +{ + zend_bool nested = EX(nested); + zend_op_array *op_array = EX(op_array); + + EG(current_execute_data) = EX(prev_execute_data); + EG(opline_ptr) = NULL; + if (!EG(active_symbol_table)) { + i_free_compiled_variables(execute_data); + } + + zend_vm_stack_free((char*)execute_data - (ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T) TSRMLS_CC); + + if ((op_array->fn_flags & ZEND_ACC_CLOSURE) && op_array->prototype) { + zval_ptr_dtor((zval**)&op_array->prototype); + } + + if (nested) { + execute_data = EG(current_execute_data); + } + if (nested) { + USE_OPLINE + + LOAD_REGS(); + LOAD_OPLINE(); + if (UNEXPECTED(opline->opcode == ZEND_INCLUDE_OR_EVAL)) { + + EX(function_state).function = (zend_function *) EX(op_array); + EX(function_state).arguments = NULL; + + EG(opline_ptr) = &EX(opline); + EG(active_op_array) = EX(op_array); + EG(return_value_ptr_ptr) = EX(original_return_value); + destroy_op_array(op_array TSRMLS_CC); + efree(op_array); + if (UNEXPECTED(EG(exception) != NULL)) { + zend_throw_exception_internal(NULL TSRMLS_CC); + HANDLE_EXCEPTION_LEAVE(); + } + + ZEND_VM_INC_OPCODE(); + ZEND_VM_LEAVE(); + } else { + EG(opline_ptr) = &EX(opline); + EG(active_op_array) = EX(op_array); + EG(return_value_ptr_ptr) = EX(original_return_value); + if (EG(active_symbol_table)) { + zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC); + } + EG(active_symbol_table) = EX(symbol_table); + + EX(function_state).function = (zend_function *) EX(op_array); + EX(function_state).arguments = NULL; + + if (EG(This)) { + if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) { + if (EX(call)->is_ctor_result_used) { + Z_DELREF_P(EG(This)); + } + if (Z_REFCOUNT_P(EG(This)) == 1) { + zend_object_store_ctor_failed(EG(This) TSRMLS_CC); + } + } + zval_ptr_dtor(&EG(This)); + } + EG(This) = EX(current_this); + EG(scope) = EX(current_scope); + EG(called_scope) = EX(current_called_scope); + + EX(call)--; + + zend_vm_stack_clear_multiple(1 TSRMLS_CC); + + if (UNEXPECTED(EG(exception) != NULL)) { + zend_throw_exception_internal(NULL TSRMLS_CC); + if (RETURN_VALUE_USED(opline) && EX_T(opline->result.var).var.ptr) { + zval_ptr_dtor(&EX_T(opline->result.var).var.ptr); + } + HANDLE_EXCEPTION_LEAVE(); + } + + ZEND_VM_INC_OPCODE(); + ZEND_VM_LEAVE(); + } + } + ZEND_VM_RETURN(); +} + +ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY) +{ + USE_OPLINE + zend_bool should_change_scope = 0; + zend_function *fbc = EX(function_state).function; + + SAVE_OPLINE(); + EX(object) = EX(call)->object; + if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) { + zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name, fbc->common.function_name); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); /* Never reached */ + } + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { + zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated", + fbc->common.scope ? fbc->common.scope->name : "", + fbc->common.scope ? "::" : "", + fbc->common.function_name); + } + } + if (fbc->common.scope && + !(fbc->common.fn_flags & ZEND_ACC_STATIC) && + !EX(object)) { + + if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + /* FIXME: output identifiers properly */ + zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically", fbc->common.scope->name, fbc->common.function_name); + } else { + /* FIXME: output identifiers properly */ + /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ + zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically", fbc->common.scope->name, fbc->common.function_name); + } + } + + if (fbc->type == ZEND_USER_FUNCTION || fbc->common.scope) { + should_change_scope = 1; + EX(current_this) = EG(This); + EX(current_scope) = EG(scope); + EX(current_called_scope) = EG(called_scope); + EG(This) = EX(object); + EG(scope) = (fbc->type == ZEND_USER_FUNCTION || !EX(object)) ? fbc->common.scope : NULL; + EG(called_scope) = EX(call)->called_scope; + } + + EX(function_state).arguments = zend_vm_stack_top(TSRMLS_C); + zend_vm_stack_push((void*)(zend_uintptr_t)opline->extended_value TSRMLS_CC); + LOAD_OPLINE(); + + if (fbc->type == ZEND_INTERNAL_FUNCTION) { - temp_variable *ret = &EX_T(opline->result.var); - - MAKE_STD_ZVAL(ret->var.ptr); - ZVAL_NULL(ret->var.ptr); - ret->var.ptr_ptr = &ret->var.ptr; - ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0; - + if (fbc->common.arg_info) { + zend_uint i=0; + zval **p = (zval**)EX(function_state).arguments; + ulong arg_count = opline->extended_value; + + while (arg_count>0) { + zend_verify_arg_type(fbc, ++i, *(p-arg_count), 0 TSRMLS_CC); + arg_count--; + } + } + - 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, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC); - } else { - zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC); - } ++ if (EXPECTED(EG(exception) == NULL)) { ++ temp_variable *ret = &EX_T(opline->result.var); ++ ++ MAKE_STD_ZVAL(ret->var.ptr); ++ ZVAL_NULL(ret->var.ptr); ++ ret->var.ptr_ptr = &ret->var.ptr; ++ ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0; ++ ++ 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, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC); ++ } else { ++ zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC); ++ } + - if (!RETURN_VALUE_USED(opline)) { - zval_ptr_dtor(&ret->var.ptr); ++ if (!RETURN_VALUE_USED(opline)) { ++ zval_ptr_dtor(&ret->var.ptr); ++ } + } + } else if (fbc->type == ZEND_USER_FUNCTION) { + EX(original_return_value) = EG(return_value_ptr_ptr); + EG(active_symbol_table) = NULL; + EG(active_op_array) = &fbc->op_array; + EG(return_value_ptr_ptr) = NULL; + if (RETURN_VALUE_USED(opline)) { + temp_variable *ret = &EX_T(opline->result.var); + + ret->var.ptr = NULL; + EG(return_value_ptr_ptr) = &ret->var.ptr; + ret->var.ptr_ptr = &ret->var.ptr; + ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0; + } + + if (UNEXPECTED((EG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { + if (RETURN_VALUE_USED(opline)) { + EX_T(opline->result.var).var.ptr = zend_generator_create_zval(EG(active_op_array) TSRMLS_CC); + } + } else if (EXPECTED(zend_execute_ex == execute_ex)) { + if (EXPECTED(EG(exception) == NULL)) { + ZEND_VM_ENTER(); + } + } else { + zend_execute(EG(active_op_array) TSRMLS_CC); + } + + EG(opline_ptr) = &EX(opline); + EG(active_op_array) = EX(op_array); + EG(return_value_ptr_ptr) = EX(original_return_value); + if (EG(active_symbol_table)) { + zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC); + } + EG(active_symbol_table) = EX(symbol_table); + } else { /* ZEND_OVERLOADED_FUNCTION */ + MAKE_STD_ZVAL(EX_T(opline->result.var).var.ptr); + ZVAL_NULL(EX_T(opline->result.var).var.ptr); + + /* 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); + } else { + zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object"); + } + + if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { + efree((char*)fbc->common.function_name); + } + efree(fbc); + + if (!RETURN_VALUE_USED(opline)) { + zval_ptr_dtor(&EX_T(opline->result.var).var.ptr); + } else { + Z_UNSET_ISREF_P(EX_T(opline->result.var).var.ptr); + Z_SET_REFCOUNT_P(EX_T(opline->result.var).var.ptr, 1); + EX_T(opline->result.var).var.fcall_returned_reference = 0; + EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr; + } + } + + EX(function_state).function = (zend_function *) EX(op_array); + EX(function_state).arguments = NULL; + + if (should_change_scope) { + if (EG(This)) { + if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) { + if (EX(call)->is_ctor_result_used) { + Z_DELREF_P(EG(This)); + } + if (Z_REFCOUNT_P(EG(This)) == 1) { + zend_object_store_ctor_failed(EG(This) TSRMLS_CC); + } + } + zval_ptr_dtor(&EG(This)); + } + EG(This) = EX(current_this); + EG(scope) = EX(current_scope); + EG(called_scope) = EX(current_called_scope); + } + + EX(call)--; + + zend_vm_stack_clear_multiple(1 TSRMLS_CC); + + if (UNEXPECTED(EG(exception) != NULL)) { + zend_throw_exception_internal(NULL TSRMLS_CC); + if (RETURN_VALUE_USED(opline) && EX_T(opline->result.var).var.ptr) { + zval_ptr_dtor(&EX_T(opline->result.var).var.ptr); + } + HANDLE_EXCEPTION(); + } + + ZEND_VM_NEXT_OPCODE(); +} + ZEND_VM_HANDLER(42, ZEND_JMP, ANY, ANY) { USE_OPLINE diff --cc Zend/zend_vm_execute.h index d65dfc4,1860a0f..7fe6ee1 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@@ -519,13 -619,8 +519,6 @@@ static int ZEND_FASTCALL zend_do_fcall_ LOAD_OPLINE(); if (fbc->type == ZEND_INTERNAL_FUNCTION) { -- temp_variable *ret = &EX_T(opline->result.var); -- - MAKE_STD_ZVAL(ret->var.ptr); - ZVAL_NULL(ret->var.ptr); - ret->var.ptr_ptr = &ret->var.ptr; - ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0; - if (fbc->common.arg_info) { zend_uint i=0; zval **p = (zval**)EX(function_state).arguments; @@@ -537,15 -632,22 +530,24 @@@ } } - 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, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC); - } else { - zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC); - } + if (EXPECTED(EG(exception) == NULL)) { ++ temp_variable *ret = &EX_T(opline->result.var); + - if (!RETURN_VALUE_USED(opline)) { - zval_ptr_dtor(&ret->var.ptr); + MAKE_STD_ZVAL(ret->var.ptr); + ZVAL_NULL(ret->var.ptr); + ret->var.ptr_ptr = &ret->var.ptr; + ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0; + + 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, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC); + } else { - zend_execute_internal(execute_data, RETURN_VALUE_USED(opline) TSRMLS_CC); ++ zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC); + } + + if (!RETURN_VALUE_USED(opline)) { + zval_ptr_dtor(&ret->var.ptr); + } } } else if (fbc->type == ZEND_USER_FUNCTION) { EX(original_return_value) = EG(return_value_ptr_ptr);
diff --cc Zend/zend_vm_def.h index 206a233,ffa94a1..31a5fac --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@@ -1829,266 -1819,6 +1829,268 @@@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VA ZEND_VM_NEXT_OPCODE(); } +ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) +{ + zend_bool nested = EX(nested); + zend_op_array *op_array = EX(op_array); + + EG(current_execute_data) = EX(prev_execute_data); + EG(opline_ptr) = NULL; + if (!EG(active_symbol_table)) { + i_free_compiled_variables(execute_data); + } + + zend_vm_stack_free((char*)execute_data - (ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T) TSRMLS_CC); + + if ((op_array->fn_flags & ZEND_ACC_CLOSURE) && op_array->prototype) { + zval_ptr_dtor((zval**)&op_array->prototype); + } + + if (nested) { + execute_data = EG(current_execute_data); + } + if (nested) { + USE_OPLINE + + LOAD_REGS(); + LOAD_OPLINE(); + if (UNEXPECTED(opline->opcode == ZEND_INCLUDE_OR_EVAL)) { + + EX(function_state).function = (zend_function *) EX(op_array); + EX(function_state).arguments = NULL; + + EG(opline_ptr) = &EX(opline); + EG(active_op_array) = EX(op_array); + EG(return_value_ptr_ptr) = EX(original_return_value); + destroy_op_array(op_array TSRMLS_CC); + efree(op_array); + if (UNEXPECTED(EG(exception) != NULL)) { + zend_throw_exception_internal(NULL TSRMLS_CC); + HANDLE_EXCEPTION_LEAVE(); + } + + ZEND_VM_INC_OPCODE(); + ZEND_VM_LEAVE(); + } else { + EG(opline_ptr) = &EX(opline); + EG(active_op_array) = EX(op_array); + EG(return_value_ptr_ptr) = EX(original_return_value); + if (EG(active_symbol_table)) { + zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC); + } + EG(active_symbol_table) = EX(symbol_table); + + EX(function_state).function = (zend_function *) EX(op_array); + EX(function_state).arguments = NULL; + + if (EG(This)) { + if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) { + if (EX(call)->is_ctor_result_used) { + Z_DELREF_P(EG(This)); + } + if (Z_REFCOUNT_P(EG(This)) == 1) { + zend_object_store_ctor_failed(EG(This) TSRMLS_CC); + } + } + zval_ptr_dtor(&EG(This)); + } + EG(This) = EX(current_this); + EG(scope) = EX(current_scope); + EG(called_scope) = EX(current_called_scope); + + EX(call)--; + + zend_vm_stack_clear_multiple(1 TSRMLS_CC); + + if (UNEXPECTED(EG(exception) != NULL)) { + zend_throw_exception_internal(NULL TSRMLS_CC); + if (RETURN_VALUE_USED(opline) && EX_T(opline->result.var).var.ptr) { + zval_ptr_dtor(&EX_T(opline->result.var).var.ptr); + } + HANDLE_EXCEPTION_LEAVE(); + } + + ZEND_VM_INC_OPCODE(); + ZEND_VM_LEAVE(); + } + } + ZEND_VM_RETURN(); +} + +ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY) +{ + USE_OPLINE + zend_bool should_change_scope = 0; + zend_function *fbc = EX(function_state).function; + + SAVE_OPLINE(); + EX(object) = EX(call)->object; + if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) { + zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name, fbc->common.function_name); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); /* Never reached */ + } + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { + zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated", + fbc->common.scope ? fbc->common.scope->name : "", + fbc->common.scope ? "::" : "", + fbc->common.function_name); + } + } + if (fbc->common.scope && + !(fbc->common.fn_flags & ZEND_ACC_STATIC) && + !EX(object)) { + + if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + /* FIXME: output identifiers properly */ + zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically", fbc->common.scope->name, fbc->common.function_name); + } else { + /* FIXME: output identifiers properly */ + /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ + zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically", fbc->common.scope->name, fbc->common.function_name); + } + } + + if (fbc->type == ZEND_USER_FUNCTION || fbc->common.scope) { + should_change_scope = 1; + EX(current_this) = EG(This); + EX(current_scope) = EG(scope); + EX(current_called_scope) = EG(called_scope); + EG(This) = EX(object); + EG(scope) = (fbc->type == ZEND_USER_FUNCTION || !EX(object)) ? fbc->common.scope : NULL; + EG(called_scope) = EX(call)->called_scope; + } + + EX(function_state).arguments = zend_vm_stack_top(TSRMLS_C); + zend_vm_stack_push((void*)(zend_uintptr_t)opline->extended_value TSRMLS_CC); + LOAD_OPLINE(); + + if (fbc->type == ZEND_INTERNAL_FUNCTION) { - temp_variable *ret = &EX_T(opline->result.var); - - MAKE_STD_ZVAL(ret->var.ptr); - ZVAL_NULL(ret->var.ptr); - ret->var.ptr_ptr = &ret->var.ptr; - ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0; - + if (fbc->common.arg_info) { + zend_uint i=0; + zval **p = (zval**)EX(function_state).arguments; + ulong arg_count = opline->extended_value; + + while (arg_count>0) { + zend_verify_arg_type(fbc, ++i, *(p-arg_count), 0 TSRMLS_CC); + arg_count--; + } + } + - 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, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC); - } else { - zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC); - } ++ if (EXPECTED(EG(exception) == NULL)) { ++ temp_variable *ret = &EX_T(opline->result.var); ++ ++ MAKE_STD_ZVAL(ret->var.ptr); ++ ZVAL_NULL(ret->var.ptr); ++ ret->var.ptr_ptr = &ret->var.ptr; ++ ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0; ++ ++ 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, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC); ++ } else { ++ zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC); ++ } + - if (!RETURN_VALUE_USED(opline)) { - zval_ptr_dtor(&ret->var.ptr); ++ if (!RETURN_VALUE_USED(opline)) { ++ zval_ptr_dtor(&ret->var.ptr); ++ } + } + } else if (fbc->type == ZEND_USER_FUNCTION) { + EX(original_return_value) = EG(return_value_ptr_ptr); + EG(active_symbol_table) = NULL; + EG(active_op_array) = &fbc->op_array; + EG(return_value_ptr_ptr) = NULL; + if (RETURN_VALUE_USED(opline)) { + temp_variable *ret = &EX_T(opline->result.var); + + ret->var.ptr = NULL; + EG(return_value_ptr_ptr) = &ret->var.ptr; + ret->var.ptr_ptr = &ret->var.ptr; + ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0; + } + + if (UNEXPECTED((EG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { + if (RETURN_VALUE_USED(opline)) { + EX_T(opline->result.var).var.ptr = zend_generator_create_zval(EG(active_op_array) TSRMLS_CC); + } + } else if (EXPECTED(zend_execute_ex == execute_ex)) { + if (EXPECTED(EG(exception) == NULL)) { + ZEND_VM_ENTER(); + } + } else { + zend_execute(EG(active_op_array) TSRMLS_CC); + } + + EG(opline_ptr) = &EX(opline); + EG(active_op_array) = EX(op_array); + EG(return_value_ptr_ptr) = EX(original_return_value); + if (EG(active_symbol_table)) { + zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC); + } + EG(active_symbol_table) = EX(symbol_table); + } else { /* ZEND_OVERLOADED_FUNCTION */ + MAKE_STD_ZVAL(EX_T(opline->result.var).var.ptr); + ZVAL_NULL(EX_T(opline->result.var).var.ptr); + + /* 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); + } else { + zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object"); + } + + if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { + efree((char*)fbc->common.function_name); + } + efree(fbc); + + if (!RETURN_VALUE_USED(opline)) { + zval_ptr_dtor(&EX_T(opline->result.var).var.ptr); + } else { + Z_UNSET_ISREF_P(EX_T(opline->result.var).var.ptr); + Z_SET_REFCOUNT_P(EX_T(opline->result.var).var.ptr, 1); + EX_T(opline->result.var).var.fcall_returned_reference = 0; + EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr; + } + } + + EX(function_state).function = (zend_function *) EX(op_array); + EX(function_state).arguments = NULL; + + if (should_change_scope) { + if (EG(This)) { + if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) { + if (EX(call)->is_ctor_result_used) { + Z_DELREF_P(EG(This)); + } + if (Z_REFCOUNT_P(EG(This)) == 1) { + zend_object_store_ctor_failed(EG(This) TSRMLS_CC); + } + } + zval_ptr_dtor(&EG(This)); + } + EG(This) = EX(current_this); + EG(scope) = EX(current_scope); + EG(called_scope) = EX(current_called_scope); + } + + EX(call)--; + + zend_vm_stack_clear_multiple(1 TSRMLS_CC); + + if (UNEXPECTED(EG(exception) != NULL)) { + zend_throw_exception_internal(NULL TSRMLS_CC); + if (RETURN_VALUE_USED(opline) && EX_T(opline->result.var).var.ptr) { + zval_ptr_dtor(&EX_T(opline->result.var).var.ptr); + } + HANDLE_EXCEPTION(); + } + + ZEND_VM_NEXT_OPCODE(); +} + ZEND_VM_HANDLER(42, ZEND_JMP, ANY, ANY) { USE_OPLINE diff --cc Zend/zend_vm_execute.h index d65dfc4,1860a0f..7fe6ee1 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@@ -519,13 -619,8 +519,6 @@@ static int ZEND_FASTCALL zend_do_fcall_ LOAD_OPLINE(); if (fbc->type == ZEND_INTERNAL_FUNCTION) { -- temp_variable *ret = &EX_T(opline->result.var); -- - MAKE_STD_ZVAL(ret->var.ptr); - ZVAL_NULL(ret->var.ptr); - ret->var.ptr_ptr = &ret->var.ptr; - ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0; - if (fbc->common.arg_info) { zend_uint i=0; zval **p = (zval**)EX(function_state).arguments; @@@ -537,15 -632,22 +530,24 @@@ } } - 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, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC); - } else { - zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC); - } + if (EXPECTED(EG(exception) == NULL)) { ++ temp_variable *ret = &EX_T(opline->result.var); + - if (!RETURN_VALUE_USED(opline)) { - zval_ptr_dtor(&ret->var.ptr); + MAKE_STD_ZVAL(ret->var.ptr); + ZVAL_NULL(ret->var.ptr); + ret->var.ptr_ptr = &ret->var.ptr; + ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0; + + 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, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC); + } else { - zend_execute_internal(execute_data, RETURN_VALUE_USED(opline) TSRMLS_CC); ++ zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC); + } + + if (!RETURN_VALUE_USED(opline)) { + zval_ptr_dtor(&ret->var.ptr); + } } } else if (fbc->type == ZEND_USER_FUNCTION) { EX(original_return_value) = EG(return_value_ptr_ptr);