From 529bf737ca388ad56fb4ae20ccb81e6276f25ec0 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 9 Apr 2015 21:42:23 +0300 Subject: [PATCH] Accurate use of proxy_call --- Zend/zend_API.c | 28 +++----- Zend/zend_builtin_functions.c | 3 +- Zend/zend_object_handlers.c | 109 ++------------------------------ Zend/zend_object_handlers.h | 1 - Zend/zend_objects_API.c | 4 +- Zend/zend_objects_API.h | 2 +- ext/reflection/php_reflection.c | 11 ++-- 7 files changed, 23 insertions(+), 135 deletions(-) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 273e9e9f6ab..8ca697b2e05 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -3070,16 +3070,7 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca get_function_via_handler: if (fcc->object && fcc->calling_scope == ce_org) { if (strict_class && ce_org->__call) { - fcc->function_handler = emalloc(sizeof(zend_internal_function)); - fcc->function_handler->internal_function.type = ZEND_INTERNAL_FUNCTION; - fcc->function_handler->internal_function.module = (ce_org->type == ZEND_INTERNAL_CLASS) ? ce_org->info.internal.module : NULL; - fcc->function_handler->internal_function.handler = zend_std_call_user_call; - fcc->function_handler->internal_function.arg_info = NULL; - fcc->function_handler->internal_function.num_args = 0; - fcc->function_handler->internal_function.scope = ce_org; - fcc->function_handler->internal_function.fn_flags = ZEND_ACC_CALL_VIA_HANDLER; - fcc->function_handler->internal_function.function_name = mname; - zend_string_addref(mname); + fcc->function_handler = zend_get_proxy_call_func(ce_org, mname, 0); call_via_handler = 1; retval = 1; } else if (fcc->object->handlers->get_method) { @@ -3092,7 +3083,7 @@ get_function_via_handler: if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) { zend_string_release(fcc->function_handler->common.function_name); } - efree(fcc->function_handler); + zend_free_proxy_call_func(fcc->function_handler); } } else { retval = 1; @@ -3250,14 +3241,13 @@ again: ret = zend_is_callable_check_func(check_flags, callable, fcc, 0, error); if (fcc == &fcc_local && fcc->function_handler && - ((fcc->function_handler->type == ZEND_INTERNAL_FUNCTION && - (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER)) || + ((fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) || fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY || fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) { if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) { zend_string_release(fcc->function_handler->common.function_name); } - efree(fcc->function_handler); + zend_free_proxy_call_func(fcc->function_handler); } return ret; @@ -3338,14 +3328,13 @@ again: ret = zend_is_callable_check_func(check_flags, method, fcc, strict_class, error); if (fcc == &fcc_local && fcc->function_handler && - ((fcc->function_handler->type == ZEND_INTERNAL_FUNCTION && - (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER)) || + ((fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) || fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY || fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) { if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) { zend_string_release(fcc->function_handler->common.function_name); } - efree(fcc->function_handler); + zend_free_proxy_call_func(fcc->function_handler); } return ret; @@ -3414,14 +3403,13 @@ ZEND_API zend_bool zend_make_callable(zval *callable, zend_string **callable_nam add_next_index_str(callable, zend_string_copy(fcc.function_handler->common.function_name)); } if (fcc.function_handler && - ((fcc.function_handler->type == ZEND_INTERNAL_FUNCTION && - (fcc.function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER)) || + ((fcc.function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) || fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY || fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION)) { if (fcc.function_handler->type != ZEND_OVERLOADED_FUNCTION) { zend_string_release(fcc.function_handler->common.function_name); } - efree(fcc.function_handler); + zend_free_proxy_call_func(fcc.function_handler); } return 1; } diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 9f62a4b8c9a..bc3e9cbaf50 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -2506,8 +2506,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int if (prev_call && prev_call->func && !ZEND_USER_CODE(prev_call->func->common.type) && - !(prev_call->func->common.type == ZEND_INTERNAL_FUNCTION && - (prev_call->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER))) { + !(prev_call->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER)) { break; } if (prev->func && ZEND_USER_CODE(prev->func->common.type)) { diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 9d968c38577..7230b46fa4e 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -915,47 +915,6 @@ static void zend_std_unset_dimension(zval *object, zval *offset) /* {{{ */ } /* }}} */ -ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */ -{ - zend_internal_function *func = (zend_internal_function *)EX(func); - zval method_name, method_args; - zval method_result; - zend_class_entry *ce = Z_OBJCE_P(getThis()); - - array_init_size(&method_args, ZEND_NUM_ARGS()); - - if (UNEXPECTED(zend_copy_parameters_array(ZEND_NUM_ARGS(), &method_args) == FAILURE)) { - zval_dtor(&method_args); - zend_error(E_EXCEPTION | E_ERROR, "Cannot get arguments for __call"); - RETURN_FALSE; - } - - ZVAL_STR(&method_name, func->function_name); /* no dup - it's a copy */ - - /* __call handler is called with two arguments: - method name - array of method parameters - - */ - zend_call_method_with_2_params(getThis(), ce, &ce->__call, ZEND_CALL_FUNC_NAME, &method_result, &method_name, &method_args); - - if (Z_TYPE(method_result) != IS_UNDEF) { - RETVAL_ZVAL_FAST(&method_result); - zval_ptr_dtor(&method_result); - } - - /* now destruct all auxiliaries */ - zval_ptr_dtor(&method_args); - zval_ptr_dtor(&method_name); - - /* destruct the function also, then - we have allocated it in get_method */ - efree_size(func, sizeof(zend_internal_function)); -#if ZEND_DEBUG - execute_data->func = NULL; -#endif -} -/* }}} */ - /* Ensures that we're allowed to call a private method. * Returns the function address that should be called, or NULL * if no such function exists. @@ -1034,12 +993,6 @@ ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope) } /* }}} */ -static inline union _zend_function *zend_get_user_call_function(zend_class_entry *ce, zend_string *method_name) /* {{{ */ -{ - return (union _zend_function *)zend_get_proxy_call_func(ce, method_name, 0); -} -/* }}} */ - static union _zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string *method_name, const zval *key) /* {{{ */ { zend_object *zobj = *obj_ptr; @@ -1063,7 +1016,7 @@ static union _zend_function *zend_std_get_method(zend_object **obj_ptr, zend_str STR_ALLOCA_FREE(lc_method_name, use_heap); } if (zobj->ce->__call) { - return zend_get_user_call_function(zobj->ce, method_name); + return zend_get_proxy_call_func(zobj->ce, method_name, 0); } else { return NULL; } @@ -1082,7 +1035,7 @@ static union _zend_function *zend_std_get_method(zend_object **obj_ptr, zend_str fbc = updated_fbc; } else { if (zobj->ce->__call) { - fbc = zend_get_user_call_function(zobj->ce, method_name); + fbc = zend_get_proxy_call_func(zobj->ce, method_name, 0); } else { zend_error(E_EXCEPTION | E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name->val, EG(scope) ? EG(scope)->name->val : ""); fbc = NULL; @@ -1109,7 +1062,7 @@ static union _zend_function *zend_std_get_method(zend_object **obj_ptr, zend_str */ if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(fbc), EG(scope)))) { if (zobj->ce->__call) { - fbc = zend_get_user_call_function(zobj->ce, method_name); + fbc = zend_get_proxy_call_func(zobj->ce, method_name, 0); } else { zend_error(E_EXCEPTION | E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name->val, EG(scope) ? EG(scope)->name->val : ""); fbc = NULL; @@ -1125,54 +1078,6 @@ static union _zend_function *zend_std_get_method(zend_object **obj_ptr, zend_str } /* }}} */ -ZEND_API void zend_std_callstatic_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */ -{ - zend_internal_function *func = (zend_internal_function *)EX(func); - zval method_name, method_args; - zval method_result; - zend_class_entry *ce = EG(scope); - - array_init_size(&method_args, ZEND_NUM_ARGS()); - - if (UNEXPECTED(zend_copy_parameters_array(ZEND_NUM_ARGS(), &method_args) == FAILURE)) { - zval_dtor(&method_args); - zend_error(E_EXCEPTION | E_ERROR, "Cannot get arguments for " ZEND_CALLSTATIC_FUNC_NAME); - RETURN_FALSE; - } - - ZVAL_STR(&method_name, func->function_name); /* no dup - it's a copy */ - - /* __callStatic handler is called with two arguments: - method name - array of method parameters - */ - zend_call_method_with_2_params(NULL, ce, &ce->__callstatic, ZEND_CALLSTATIC_FUNC_NAME, &method_result, &method_name, &method_args); - - if (Z_TYPE(method_result) != IS_UNDEF) { - RETVAL_ZVAL_FAST(&method_result); - zval_ptr_dtor(&method_result); - } - - /* now destruct all auxiliaries */ - zval_ptr_dtor(&method_args); - zval_ptr_dtor(&method_name); - - /* destruct the function also, then - we have allocated it in get_method */ - efree_size(func, sizeof(zend_internal_function)); -#if ZEND_DEBUG - execute_data->func = NULL; -#endif -} -/* }}} */ - -static inline union _zend_function *zend_get_user_callstatic_function(zend_class_entry *ce, zend_string *method_name) /* {{{ */ -{ - return (union _zend_function *)zend_get_proxy_call_func(ce, method_name, 1); -} -/* }}} */ - -/* This is not (yet?) in the API, but it belongs in the built-in objects callbacks */ - ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_string *function_name, const zval *key) /* {{{ */ { zend_function *fbc = NULL; @@ -1207,9 +1112,9 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st if (ce->__call && Z_OBJ(EG(current_execute_data)->This) && instanceof_function(Z_OBJCE(EG(current_execute_data)->This), ce)) { - return zend_get_user_call_function(ce, function_name); + return zend_get_proxy_call_func(ce, function_name, 0); } else if (ce->__callstatic) { - return zend_get_user_callstatic_function(ce, function_name); + return zend_get_proxy_call_func(ce, function_name, 1); } else { return NULL; } @@ -1235,7 +1140,7 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st fbc = updated_fbc; } else { if (ce->__callstatic) { - fbc = zend_get_user_callstatic_function(ce, function_name); + fbc = zend_get_proxy_call_func(ce, function_name, 1); } else { zend_error(E_EXCEPTION | E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), function_name->val, EG(scope) ? EG(scope)->name->val : ""); fbc = NULL; @@ -1246,7 +1151,7 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st */ if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(fbc), EG(scope)))) { if (ce->__callstatic) { - fbc = zend_get_user_callstatic_function(ce, function_name); + fbc = zend_get_proxy_call_func(ce, function_name, 1); } else { zend_error(E_EXCEPTION | E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), function_name->val, EG(scope) ? EG(scope)->name->val : ""); fbc = NULL; diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h index c537a161730..8655869be61 100644 --- a/Zend/zend_object_handlers.h +++ b/Zend/zend_object_handlers.h @@ -179,7 +179,6 @@ ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope) ZEND_API int zend_check_property_access(zend_object *zobj, zend_string *prop_info_name); -ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS); END_EXTERN_C() #endif diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c index e9d46fb38bb..552f4ae483a 100644 --- a/Zend/zend_objects_API.c +++ b/Zend/zend_objects_API.c @@ -242,7 +242,7 @@ ZEND_API void zend_init_proxy_call_func(zend_op_array *func, zend_op *opline) func->opcodes = opline; } -ZEND_API zend_op_array *zend_get_proxy_call_func(zend_class_entry *ce, zend_string *method_name, int is_static) +ZEND_API zend_function *zend_get_proxy_call_func(zend_class_entry *ce, zend_string *method_name, int is_static) { zend_op_array *func; zend_function *fbc = is_static? ce->__callstatic : ce->__call; @@ -273,7 +273,7 @@ ZEND_API zend_op_array *zend_get_proxy_call_func(zend_class_entry *ce, zend_stri func->function_name = zend_string_copy(method_name); } - return func; + return (zend_function*)func; } /* diff --git a/Zend/zend_objects_API.h b/Zend/zend_objects_API.h index ce8b3dda2b5..c53a61ee4e2 100644 --- a/Zend/zend_objects_API.h +++ b/Zend/zend_objects_API.h @@ -73,7 +73,7 @@ ZEND_API zend_object_handlers *zend_get_std_object_handlers(void); ZEND_API void zend_init_proxy_call_func(zend_op_array *func, zend_op *opline); -ZEND_API zend_op_array *zend_get_proxy_call_func(zend_class_entry *ce, zend_string *method_name, int is_static); +ZEND_API zend_function *zend_get_proxy_call_func(zend_class_entry *ce, zend_string *method_name, int is_static); END_EXTERN_C() diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 30a1d7b351d..f175142e168 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -265,7 +265,6 @@ static void _default_lookup_entry(zval *object, char *name, int name_len, zval * static zend_function *_copy_function(zend_function *fptr) /* {{{ */ { if (fptr - && fptr->type == ZEND_INTERNAL_FUNCTION && (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0) { zend_function *copy_fptr; @@ -283,11 +282,10 @@ static zend_function *_copy_function(zend_function *fptr) /* {{{ */ static void _free_function(zend_function *fptr) /* {{{ */ { if (fptr - && fptr->type == ZEND_INTERNAL_FUNCTION && (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0) { zend_string_release(fptr->internal_function.function_name); - efree(fptr); + zend_free_proxy_call_func(fptr); } } /* }}} */ @@ -2280,7 +2278,7 @@ ZEND_METHOD(reflection_parameter, __construct) if (fptr->type != ZEND_OVERLOADED_FUNCTION) { zend_string_release(fptr->common.function_name); } - efree(fptr); + zend_free_proxy_call_func(fptr); } if (is_closure) { zval_ptr_dtor(reference); @@ -2841,7 +2839,7 @@ ZEND_METHOD(reflection_method, getClosure) } /* This is an original closure object and __invoke is to be called. */ - if (Z_OBJCE_P(obj) == zend_ce_closure && mptr->type == ZEND_INTERNAL_FUNCTION && + if (Z_OBJCE_P(obj) == zend_ce_closure && (mptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0) { RETURN_ZVAL(obj, 1, 0); @@ -3043,8 +3041,7 @@ ZEND_METHOD(reflection_method, invokeArgs) /* * Copy the zend_function when calling via handler (e.g. Closure::__invoke()) */ - if (mptr->type == ZEND_INTERNAL_FUNCTION && - (mptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0) { + if ((mptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0) { fcc.function_handler = _copy_function(mptr); }