mirror of
https://github.com/php/php-src.git
synced 2024-09-21 18:07:23 +00:00
Accurate use of proxy_call
This commit is contained in:
parent
5d62837d5b
commit
529bf737ca
@ -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;
|
||||
}
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user