}
/* }}} */
-static int zend_is_callable_check_class(zend_string *name, zend_class_entry *scope, zend_fcall_info_cache *fcc, int *strict_class, char **error) /* {{{ */
+static zend_always_inline zend_class_entry *get_scope(zend_execute_data *frame)
+{
+ return frame && frame->func ? frame->func->common.scope : NULL;
+}
+
+static int zend_is_callable_check_class(zend_string *name, zend_class_entry *scope, zend_execute_data *frame, zend_fcall_info_cache *fcc, int *strict_class, char **error) /* {{{ */
{
int ret = 0;
zend_class_entry *ce;
if (!scope) {
if (error) *error = estrdup("cannot access \"self\" when no class scope is active");
} else {
- fcc->called_scope = zend_get_called_scope(EG(current_execute_data));
+ fcc->called_scope = zend_get_called_scope(frame);
fcc->calling_scope = scope;
if (!fcc->object) {
- fcc->object = zend_get_this_object(EG(current_execute_data));
+ fcc->object = zend_get_this_object(frame);
}
ret = 1;
}
} else if (!scope->parent) {
if (error) *error = estrdup("cannot access \"parent\" when current class scope has no parent");
} else {
- fcc->called_scope = zend_get_called_scope(EG(current_execute_data));
+ fcc->called_scope = zend_get_called_scope(frame);
fcc->calling_scope = scope->parent;
if (!fcc->object) {
- fcc->object = zend_get_this_object(EG(current_execute_data));
+ fcc->object = zend_get_this_object(frame);
}
*strict_class = 1;
ret = 1;
}
} else if (zend_string_equals_literal(lcname, "static")) {
- zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data));
+ zend_class_entry *called_scope = zend_get_called_scope(frame);
if (!called_scope) {
if (error) *error = estrdup("cannot access \"static\" when no class scope is active");
fcc->called_scope = called_scope;
fcc->calling_scope = called_scope;
if (!fcc->object) {
- fcc->object = zend_get_this_object(EG(current_execute_data));
+ fcc->object = zend_get_this_object(frame);
}
*strict_class = 1;
ret = 1;
}
} else if ((ce = zend_lookup_class(name)) != NULL) {
- zend_class_entry *scope;
- zend_execute_data *ex = EG(current_execute_data);
-
- while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
- ex = ex->prev_execute_data;
- }
- scope = ex ? ex->func->common.scope : NULL;
+ zend_class_entry *scope = get_scope(frame);
fcc->calling_scope = ce;
if (scope && !fcc->object) {
- zend_object *object = zend_get_this_object(EG(current_execute_data));
+ zend_object *object = zend_get_this_object(frame);
if (object &&
instanceof_function(object->ce, scope) &&
fcc->function_handler = NULL;
}
-static zend_always_inline int zend_is_callable_check_func(int check_flags, zval *callable, zend_fcall_info_cache *fcc, int strict_class, char **error) /* {{{ */
+static zend_always_inline int zend_is_callable_check_func(int check_flags, zval *callable, zend_execute_data *frame, zend_fcall_info_cache *fcc, int strict_class, char **error) /* {{{ */
{
zend_class_entry *ce_org = fcc->calling_scope;
int retval = 0;
if (ce_org) {
scope = ce_org;
} else {
- scope = zend_get_executed_scope();
+ scope = get_scope(frame);
}
cname = zend_string_init(Z_STRVAL_P(callable), clen, 0);
- if (!zend_is_callable_check_class(cname, scope, fcc, &strict_class, error)) {
+ if (!zend_is_callable_check_class(cname, scope, frame, fcc, &strict_class, error)) {
zend_string_release_ex(cname, 0);
return 0;
}
retval = 1;
if ((fcc->function_handler->op_array.fn_flags & ZEND_ACC_CHANGED) &&
!strict_class) {
- scope = zend_get_executed_scope();
+ scope = get_scope(frame);
if (scope &&
instanceof_function(fcc->function_handler->common.scope, scope)) {
(fcc->calling_scope &&
((fcc->object && fcc->calling_scope->__call) ||
(!fcc->object && fcc->calling_scope->__callstatic)))) {
- scope = zend_get_executed_scope();
+ scope = get_scope(frame);
if (fcc->function_handler->common.scope != scope) {
if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PRIVATE)
|| !zend_check_protected(zend_get_function_root_class(fcc->function_handler), scope)) {
retval = 1;
call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
if (call_via_handler && !fcc->object) {
- zend_object *object = zend_get_this_object(EG(current_execute_data));
+ zend_object *object = zend_get_this_object(frame);
if (object &&
instanceof_function(object->ce, fcc->calling_scope)) {
fcc->object = object;
}
if (retval
&& !(fcc->function_handler->common.fn_flags & ZEND_ACC_PUBLIC)) {
- scope = zend_get_executed_scope();
+ scope = get_scope(frame);
if (fcc->function_handler->common.scope != scope) {
if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PRIVATE)
|| (!zend_check_protected(zend_get_function_root_class(fcc->function_handler), scope))) {
}
/* }}} */
-static zend_always_inline zend_bool zend_is_callable_impl(zval *callable, zend_object *object, uint32_t check_flags, zend_fcall_info_cache *fcc, char **error) /* {{{ */
+static zend_always_inline zend_bool zend_is_callable_impl(
+ zval *callable, zend_object *object, zend_execute_data *frame,
+ uint32_t check_flags, zend_fcall_info_cache *fcc, char **error) /* {{{ */
{
zend_bool ret;
zend_fcall_info_cache fcc_local;
}
check_func:
- ret = zend_is_callable_check_func(check_flags, callable, fcc, strict_class, error);
+ ret = zend_is_callable_check_func(check_flags, callable, frame, fcc, strict_class, error);
if (fcc == &fcc_local) {
zend_release_fcall_info_cache(fcc);
}
return 1;
}
- if (!zend_is_callable_check_class(Z_STR_P(obj), zend_get_executed_scope(), fcc, &strict_class, error)) {
+ if (!zend_is_callable_check_class(Z_STR_P(obj), get_scope(frame), frame, fcc, &strict_class, error)) {
return 0;
}
ZEND_API zend_bool zend_is_callable_ex(zval *callable, zend_object *object, uint32_t check_flags, zend_string **callable_name, zend_fcall_info_cache *fcc, char **error) /* {{{ */
{
- zend_bool ret = zend_is_callable_impl(callable, object, check_flags, fcc, error);
+ /* Determine callability at the first parent user frame. */
+ zend_execute_data *frame = EG(current_execute_data);
+ while (frame && (!frame->func || !ZEND_USER_CODE(frame->func->type))) {
+ frame = frame->prev_execute_data;
+ }
+
+ zend_bool ret = zend_is_callable_impl(callable, object, frame, check_flags, fcc, error);
if (callable_name) {
*callable_name = zend_get_callable_name_ex(callable, object);
}