@@ -2850,7 +2850,12 @@ ZEND_API int zend_disable_class(const char *class_name, size_t class_name_length
28502850}
28512851/* }}} */
28522852
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 ) /* {{{ */
28542859{
28552860 int ret = 0 ;
28562861 zend_class_entry * ce ;
@@ -2866,10 +2871,10 @@ static int zend_is_callable_check_class(zend_string *name, zend_class_entry *sco
28662871 if (!scope ) {
28672872 if (error ) * error = estrdup ("cannot access \"self\" when no class scope is active" );
28682873 } else {
2869- fcc -> called_scope = zend_get_called_scope (EG ( current_execute_data ) );
2874+ fcc -> called_scope = zend_get_called_scope (frame );
28702875 fcc -> calling_scope = scope ;
28712876 if (!fcc -> object ) {
2872- fcc -> object = zend_get_this_object (EG ( current_execute_data ) );
2877+ fcc -> object = zend_get_this_object (frame );
28732878 }
28742879 ret = 1 ;
28752880 }
@@ -2879,39 +2884,33 @@ static int zend_is_callable_check_class(zend_string *name, zend_class_entry *sco
28792884 } else if (!scope -> parent ) {
28802885 if (error ) * error = estrdup ("cannot access \"parent\" when current class scope has no parent" );
28812886 } else {
2882- fcc -> called_scope = zend_get_called_scope (EG ( current_execute_data ) );
2887+ fcc -> called_scope = zend_get_called_scope (frame );
28832888 fcc -> calling_scope = scope -> parent ;
28842889 if (!fcc -> object ) {
2885- fcc -> object = zend_get_this_object (EG ( current_execute_data ) );
2890+ fcc -> object = zend_get_this_object (frame );
28862891 }
28872892 * strict_class = 1 ;
28882893 ret = 1 ;
28892894 }
28902895 } 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 );
28922897
28932898 if (!called_scope ) {
28942899 if (error ) * error = estrdup ("cannot access \"static\" when no class scope is active" );
28952900 } else {
28962901 fcc -> called_scope = called_scope ;
28972902 fcc -> calling_scope = called_scope ;
28982903 if (!fcc -> object ) {
2899- fcc -> object = zend_get_this_object (EG ( current_execute_data ) );
2904+ fcc -> object = zend_get_this_object (frame );
29002905 }
29012906 * strict_class = 1 ;
29022907 ret = 1 ;
29032908 }
29042909 } 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 );
29122911 fcc -> calling_scope = ce ;
29132912 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 );
29152914
29162915 if (object &&
29172916 instanceof_function (object -> ce , scope ) &&
@@ -2945,7 +2944,7 @@ ZEND_API void zend_release_fcall_info_cache(zend_fcall_info_cache *fcc) {
29452944 fcc -> function_handler = NULL ;
29462945}
29472946
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 ) /* {{{ */
29492948{
29502949 zend_class_entry * ce_org = fcc -> calling_scope ;
29512950 int retval = 0 ;
@@ -3010,11 +3009,11 @@ static zend_always_inline int zend_is_callable_check_func(int check_flags, zval
30103009 if (ce_org ) {
30113010 scope = ce_org ;
30123011 } else {
3013- scope = zend_get_executed_scope ( );
3012+ scope = get_scope ( frame );
30143013 }
30153014
30163015 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 )) {
30183017 zend_string_release_ex (cname , 0 );
30193018 return 0 ;
30203019 }
@@ -3053,7 +3052,7 @@ static zend_always_inline int zend_is_callable_check_func(int check_flags, zval
30533052 retval = 1 ;
30543053 if ((fcc -> function_handler -> op_array .fn_flags & ZEND_ACC_CHANGED ) &&
30553054 !strict_class ) {
3056- scope = zend_get_executed_scope ( );
3055+ scope = get_scope ( frame );
30573056 if (scope &&
30583057 instanceof_function (fcc -> function_handler -> common .scope , scope )) {
30593058
@@ -3072,7 +3071,7 @@ static zend_always_inline int zend_is_callable_check_func(int check_flags, zval
30723071 (fcc -> calling_scope &&
30733072 ((fcc -> object && fcc -> calling_scope -> __call ) ||
30743073 (!fcc -> object && fcc -> calling_scope -> __callstatic )))) {
3075- scope = zend_get_executed_scope ( );
3074+ scope = get_scope ( frame );
30763075 if (fcc -> function_handler -> common .scope != scope ) {
30773076 if ((fcc -> function_handler -> common .fn_flags & ZEND_ACC_PRIVATE )
30783077 || !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
31123111 retval = 1 ;
31133112 call_via_handler = (fcc -> function_handler -> common .fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE ) != 0 ;
31143113 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 );
31163115 if (object &&
31173116 instanceof_function (object -> ce , fcc -> calling_scope )) {
31183117 fcc -> object = object ;
@@ -3137,7 +3136,7 @@ static zend_always_inline int zend_is_callable_check_func(int check_flags, zval
31373136 }
31383137 if (retval
31393138 && !(fcc -> function_handler -> common .fn_flags & ZEND_ACC_PUBLIC )) {
3140- scope = zend_get_executed_scope ( );
3139+ scope = get_scope ( frame );
31413140 if (fcc -> function_handler -> common .scope != scope ) {
31423141 if ((fcc -> function_handler -> common .fn_flags & ZEND_ACC_PRIVATE )
31433142 || (!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) /* {{{ */
32273226}
32283227/* }}} */
32293228
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 ) /* {{{ */
32313232{
32323233 zend_bool ret ;
32333234 zend_fcall_info_cache fcc_local ;
@@ -3259,7 +3260,7 @@ static zend_always_inline zend_bool zend_is_callable_impl(zval *callable, zend_o
32593260 }
32603261
32613262check_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 );
32633264 if (fcc == & fcc_local ) {
32643265 zend_release_fcall_info_cache (fcc );
32653266 }
@@ -3291,7 +3292,7 @@ static zend_always_inline zend_bool zend_is_callable_impl(zval *callable, zend_o
32913292 return 1 ;
32923293 }
32933294
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 )) {
32953296 return 0 ;
32963297 }
32973298
@@ -3348,7 +3349,13 @@ static zend_always_inline zend_bool zend_is_callable_impl(zval *callable, zend_o
33483349
33493350ZEND_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 ) /* {{{ */
33503351{
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 );
33523359 if (callable_name ) {
33533360 * callable_name = zend_get_callable_name_ex (callable , object );
33543361 }
0 commit comments