2020
2121#include <stdio.h>
2222#include <signal.h>
23+ #include <zend_namespaces.h>
2324
2425#include "zend.h"
2526#include "zend_compile.h"
@@ -1167,13 +1168,14 @@ ZEND_API bool zend_is_valid_class_name(zend_string *name) {
11671168}
11681169
11691170static zend_string * get_namespace_from_scope (const zend_class_entry * scope ) {
1171+ ZEND_ASSERT (scope != NULL );
11701172 while (scope && scope -> lexical_scope && scope -> type != ZEND_NAMESPACE_CLASS ) {
11711173 scope = scope -> lexical_scope ;
11721174 }
1173- return scope -> name ;
1175+ return zend_string_copy ( scope -> name ) ;
11741176}
11751177
1176- static zend_string * get_scoped_name (const zend_string * ns , zend_string * name ) {
1178+ static zend_string * get_scoped_name (zend_string * ns , zend_string * name ) {
11771179 // remove the matching prefix from name
11781180 name = zend_string_tolower (name );
11791181 if (ns && ZSTR_LEN (ns ) && ZSTR_LEN (name ) > ZSTR_LEN (ns ) + 1 &&
@@ -1183,10 +1185,44 @@ static zend_string *get_scoped_name(const zend_string *ns, zend_string *name) {
11831185 zend_string_release (name );
11841186 return ret ;
11851187 }
1186- zend_string_release (name );
11871188 return name ;
11881189}
11891190
1191+ zend_class_entry * zend_lookup_class_in_scope (zend_string * name , const zend_class_entry * scope ) {
1192+ zend_class_entry * ce = NULL ;
1193+ zend_string * ns_name = get_namespace_from_scope (scope );
1194+ zend_string * original_suffix = get_scoped_name (ns_name , name );
1195+ zend_string_release (ns_name );
1196+
1197+ const zend_class_entry * current_scope = scope ;
1198+
1199+ // Traverse upwards in lexical scope, stop at namespace boundary
1200+ while (current_scope && current_scope -> type != ZEND_NAMESPACE_CLASS ) {
1201+ // build fully-qualified name: current_scope->name + "\\" + original_suffix
1202+ zend_string * try_name = zend_string_concat3 (
1203+ ZSTR_VAL (current_scope -> name ), ZSTR_LEN (current_scope -> name ),
1204+ "\\" , 1 ,
1205+ ZSTR_VAL (original_suffix ), ZSTR_LEN (original_suffix )
1206+ );
1207+
1208+ zend_string * lc_try_name = zend_string_tolower (try_name );
1209+ zend_string_release (try_name );
1210+
1211+ ce = zend_hash_find_ptr (EG (class_table ), lc_try_name );
1212+ zend_string_release (lc_try_name );
1213+
1214+ if (ce ) {
1215+ zend_string_release (original_suffix );
1216+ return ce ;
1217+ }
1218+
1219+ current_scope = current_scope -> lexical_scope ;
1220+ }
1221+
1222+ zend_string_release (original_suffix );
1223+ return NULL ;
1224+ }
1225+
11901226ZEND_API zend_class_entry * zend_lookup_class_ex (zend_string * name , zend_string * key , uint32_t flags ) /* {{{ */
11911227{
11921228 zend_class_entry * ce = NULL ;
@@ -1205,26 +1241,25 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string *
12051241
12061242 if (!zend_is_compiling ()) {
12071243 const zend_class_entry * scope = zend_get_executed_scope ();
1208- if (scope && scope -> lexical_scope && scope -> lexical_scope -> type != ZEND_NAMESPACE_CLASS ) {
1209- zend_string * ns_name = get_namespace_from_scope (scope );
1210- zend_string * scoped_name = get_scoped_name (ns_name , name );
1211- while (scope -> type != ZEND_NAMESPACE_CLASS ) {
1212- zend_string * try_name = zend_string_concat3 (ZSTR_VAL (scope -> name ), ZSTR_LEN (scope -> name ), "\\" , 1 , ZSTR_VAL (scoped_name ), ZSTR_LEN (scoped_name ));
1213- lc_name = zend_string_tolower (try_name );
1214- ce = zend_hash_find_ptr (EG (class_table ), lc_name );
1215- if (ce ) {
1216- zend_string_release (lc_name );
1217- zend_string_release (scoped_name );
1218- zend_string_release (ns_name );
1219- zend_string_release (try_name );
1220- return ce ;
1244+ if (scope ) {
1245+ ce = zend_lookup_class_in_scope (name , scope );
1246+ if (ce ) {
1247+ if (ce_cache ) {
1248+ SET_CE_CACHE (ce_cache , ce );
12211249 }
1222- scope = scope -> lexical_scope ;
1223- zend_string_release (lc_name );
1224- zend_string_release (try_name );
1250+ return ce ;
1251+ }
1252+ }
1253+ } else if (CG (active_class_entry )) {
1254+ const zend_class_entry * scope = CG (active_class_entry );
1255+ if (scope ) {
1256+ ce = zend_lookup_class_in_scope (name , scope );
1257+ if (ce ) {
1258+ if (ce_cache ) {
1259+ SET_CE_CACHE (ce_cache , ce );
1260+ }
1261+ return ce ;
12251262 }
1226- zend_string_release (ns_name );
1227- zend_string_release (scoped_name );
12281263 }
12291264 }
12301265
0 commit comments