@@ -2850,7 +2850,12 @@ ZEND_API int zend_disable_class(const char *class_name, size_t class_name_length
2850
2850
}
2851
2851
/* }}} */
2852
2852
2853
- static int zend_is_callable_check_class (zend_string * name , zend_class_entry * scope , zend_fcall_info_cache * fcc , int * strict_class , char * * error ) /* {{{ */
2853
+ static zend_always_inline zend_class_entry * get_scope (zend_execute_data * frame )
2854
+ {
2855
+ return frame && frame -> func ? frame -> func -> common .scope : NULL ;
2856
+ }
2857
+
2858
+ 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 ) /* {{{ */
2854
2859
{
2855
2860
int ret = 0 ;
2856
2861
zend_class_entry * ce ;
@@ -2866,10 +2871,10 @@ static int zend_is_callable_check_class(zend_string *name, zend_class_entry *sco
2866
2871
if (!scope ) {
2867
2872
if (error ) * error = estrdup ("cannot access \"self\" when no class scope is active" );
2868
2873
} else {
2869
- fcc -> called_scope = zend_get_called_scope (EG ( current_execute_data ) );
2874
+ fcc -> called_scope = zend_get_called_scope (frame );
2870
2875
fcc -> calling_scope = scope ;
2871
2876
if (!fcc -> object ) {
2872
- fcc -> object = zend_get_this_object (EG ( current_execute_data ) );
2877
+ fcc -> object = zend_get_this_object (frame );
2873
2878
}
2874
2879
ret = 1 ;
2875
2880
}
@@ -2879,39 +2884,33 @@ static int zend_is_callable_check_class(zend_string *name, zend_class_entry *sco
2879
2884
} else if (!scope -> parent ) {
2880
2885
if (error ) * error = estrdup ("cannot access \"parent\" when current class scope has no parent" );
2881
2886
} else {
2882
- fcc -> called_scope = zend_get_called_scope (EG ( current_execute_data ) );
2887
+ fcc -> called_scope = zend_get_called_scope (frame );
2883
2888
fcc -> calling_scope = scope -> parent ;
2884
2889
if (!fcc -> object ) {
2885
- fcc -> object = zend_get_this_object (EG ( current_execute_data ) );
2890
+ fcc -> object = zend_get_this_object (frame );
2886
2891
}
2887
2892
* strict_class = 1 ;
2888
2893
ret = 1 ;
2889
2894
}
2890
2895
} else if (zend_string_equals_literal (lcname , "static" )) {
2891
- zend_class_entry * called_scope = zend_get_called_scope (EG ( current_execute_data ) );
2896
+ zend_class_entry * called_scope = zend_get_called_scope (frame );
2892
2897
2893
2898
if (!called_scope ) {
2894
2899
if (error ) * error = estrdup ("cannot access \"static\" when no class scope is active" );
2895
2900
} else {
2896
2901
fcc -> called_scope = called_scope ;
2897
2902
fcc -> calling_scope = called_scope ;
2898
2903
if (!fcc -> object ) {
2899
- fcc -> object = zend_get_this_object (EG ( current_execute_data ) );
2904
+ fcc -> object = zend_get_this_object (frame );
2900
2905
}
2901
2906
* strict_class = 1 ;
2902
2907
ret = 1 ;
2903
2908
}
2904
2909
} else if ((ce = zend_lookup_class (name )) != NULL ) {
2905
- zend_class_entry * scope ;
2906
- zend_execute_data * ex = EG (current_execute_data );
2907
-
2908
- while (ex && (!ex -> func || !ZEND_USER_CODE (ex -> func -> type ))) {
2909
- ex = ex -> prev_execute_data ;
2910
- }
2911
- scope = ex ? ex -> func -> common .scope : NULL ;
2910
+ zend_class_entry * scope = get_scope (frame );
2912
2911
fcc -> calling_scope = ce ;
2913
2912
if (scope && !fcc -> object ) {
2914
- zend_object * object = zend_get_this_object (EG ( current_execute_data ) );
2913
+ zend_object * object = zend_get_this_object (frame );
2915
2914
2916
2915
if (object &&
2917
2916
instanceof_function (object -> ce , scope ) &&
@@ -2945,7 +2944,7 @@ ZEND_API void zend_release_fcall_info_cache(zend_fcall_info_cache *fcc) {
2945
2944
fcc -> function_handler = NULL ;
2946
2945
}
2947
2946
2948
- 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 ) /* {{{ */
2947
+ 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 ) /* {{{ */
2949
2948
{
2950
2949
zend_class_entry * ce_org = fcc -> calling_scope ;
2951
2950
int retval = 0 ;
@@ -3010,11 +3009,11 @@ static zend_always_inline int zend_is_callable_check_func(int check_flags, zval
3010
3009
if (ce_org ) {
3011
3010
scope = ce_org ;
3012
3011
} else {
3013
- scope = zend_get_executed_scope ( );
3012
+ scope = get_scope ( frame );
3014
3013
}
3015
3014
3016
3015
cname = zend_string_init (Z_STRVAL_P (callable ), clen , 0 );
3017
- if (!zend_is_callable_check_class (cname , scope , fcc , & strict_class , error )) {
3016
+ if (!zend_is_callable_check_class (cname , scope , frame , fcc , & strict_class , error )) {
3018
3017
zend_string_release_ex (cname , 0 );
3019
3018
return 0 ;
3020
3019
}
@@ -3053,7 +3052,7 @@ static zend_always_inline int zend_is_callable_check_func(int check_flags, zval
3053
3052
retval = 1 ;
3054
3053
if ((fcc -> function_handler -> op_array .fn_flags & ZEND_ACC_CHANGED ) &&
3055
3054
!strict_class ) {
3056
- scope = zend_get_executed_scope ( );
3055
+ scope = get_scope ( frame );
3057
3056
if (scope &&
3058
3057
instanceof_function (fcc -> function_handler -> common .scope , scope )) {
3059
3058
@@ -3072,7 +3071,7 @@ static zend_always_inline int zend_is_callable_check_func(int check_flags, zval
3072
3071
(fcc -> calling_scope &&
3073
3072
((fcc -> object && fcc -> calling_scope -> __call ) ||
3074
3073
(!fcc -> object && fcc -> calling_scope -> __callstatic )))) {
3075
- scope = zend_get_executed_scope ( );
3074
+ scope = get_scope ( frame );
3076
3075
if (fcc -> function_handler -> common .scope != scope ) {
3077
3076
if ((fcc -> function_handler -> common .fn_flags & ZEND_ACC_PRIVATE )
3078
3077
|| !zend_check_protected (zend_get_function_root_class (fcc -> function_handler ), scope )) {
@@ -3112,7 +3111,7 @@ static zend_always_inline int zend_is_callable_check_func(int check_flags, zval
3112
3111
retval = 1 ;
3113
3112
call_via_handler = (fcc -> function_handler -> common .fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE ) != 0 ;
3114
3113
if (call_via_handler && !fcc -> object ) {
3115
- zend_object * object = zend_get_this_object (EG ( current_execute_data ) );
3114
+ zend_object * object = zend_get_this_object (frame );
3116
3115
if (object &&
3117
3116
instanceof_function (object -> ce , fcc -> calling_scope )) {
3118
3117
fcc -> object = object ;
@@ -3137,7 +3136,7 @@ static zend_always_inline int zend_is_callable_check_func(int check_flags, zval
3137
3136
}
3138
3137
if (retval
3139
3138
&& !(fcc -> function_handler -> common .fn_flags & ZEND_ACC_PUBLIC )) {
3140
- scope = zend_get_executed_scope ( );
3139
+ scope = get_scope ( frame );
3141
3140
if (fcc -> function_handler -> common .scope != scope ) {
3142
3141
if ((fcc -> function_handler -> common .fn_flags & ZEND_ACC_PRIVATE )
3143
3142
|| (!zend_check_protected (zend_get_function_root_class (fcc -> function_handler ), scope ))) {
@@ -3227,7 +3226,9 @@ ZEND_API zend_string *zend_get_callable_name(zval *callable) /* {{{ */
3227
3226
}
3228
3227
/* }}} */
3229
3228
3230
- 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 ) /* {{{ */
3229
+ static zend_always_inline zend_bool zend_is_callable_impl (
3230
+ zval * callable , zend_object * object , zend_execute_data * frame ,
3231
+ uint32_t check_flags , zend_fcall_info_cache * fcc , char * * error ) /* {{{ */
3231
3232
{
3232
3233
zend_bool ret ;
3233
3234
zend_fcall_info_cache fcc_local ;
@@ -3259,7 +3260,7 @@ static zend_always_inline zend_bool zend_is_callable_impl(zval *callable, zend_o
3259
3260
}
3260
3261
3261
3262
check_func :
3262
- ret = zend_is_callable_check_func (check_flags , callable , fcc , strict_class , error );
3263
+ ret = zend_is_callable_check_func (check_flags , callable , frame , fcc , strict_class , error );
3263
3264
if (fcc == & fcc_local ) {
3264
3265
zend_release_fcall_info_cache (fcc );
3265
3266
}
@@ -3291,7 +3292,7 @@ static zend_always_inline zend_bool zend_is_callable_impl(zval *callable, zend_o
3291
3292
return 1 ;
3292
3293
}
3293
3294
3294
- if (!zend_is_callable_check_class (Z_STR_P (obj ), zend_get_executed_scope () , fcc , & strict_class , error )) {
3295
+ if (!zend_is_callable_check_class (Z_STR_P (obj ), get_scope ( frame ), frame , fcc , & strict_class , error )) {
3295
3296
return 0 ;
3296
3297
}
3297
3298
@@ -3348,7 +3349,13 @@ static zend_always_inline zend_bool zend_is_callable_impl(zval *callable, zend_o
3348
3349
3349
3350
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 ) /* {{{ */
3350
3351
{
3351
- zend_bool ret = zend_is_callable_impl (callable , object , check_flags , fcc , error );
3352
+ /* Determine callability at the first parent user frame. */
3353
+ zend_execute_data * frame = EG (current_execute_data );
3354
+ while (frame && (!frame -> func || !ZEND_USER_CODE (frame -> func -> type ))) {
3355
+ frame = frame -> prev_execute_data ;
3356
+ }
3357
+
3358
+ zend_bool ret = zend_is_callable_impl (callable , object , frame , check_flags , fcc , error );
3352
3359
if (callable_name ) {
3353
3360
* callable_name = zend_get_callable_name_ex (callable , object );
3354
3361
}
0 commit comments