20
20
21
21
#include <stdio.h>
22
22
#include <signal.h>
23
+ #include <zend_namespaces.h>
23
24
24
25
#include "zend.h"
25
26
#include "zend_compile.h"
@@ -1167,13 +1168,14 @@ ZEND_API bool zend_is_valid_class_name(zend_string *name) {
1167
1168
}
1168
1169
1169
1170
static zend_string * get_namespace_from_scope (const zend_class_entry * scope ) {
1171
+ ZEND_ASSERT (scope != NULL );
1170
1172
while (scope && scope -> lexical_scope && scope -> type != ZEND_NAMESPACE_CLASS ) {
1171
1173
scope = scope -> lexical_scope ;
1172
1174
}
1173
- return scope -> name ;
1175
+ return zend_string_copy ( scope -> name ) ;
1174
1176
}
1175
1177
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 ) {
1177
1179
// remove the matching prefix from name
1178
1180
name = zend_string_tolower (name );
1179
1181
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) {
1183
1185
zend_string_release (name );
1184
1186
return ret ;
1185
1187
}
1186
- zend_string_release (name );
1187
1188
return name ;
1188
1189
}
1189
1190
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
+
1190
1226
ZEND_API zend_class_entry * zend_lookup_class_ex (zend_string * name , zend_string * key , uint32_t flags ) /* {{{ */
1191
1227
{
1192
1228
zend_class_entry * ce = NULL ;
@@ -1205,26 +1241,25 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string *
1205
1241
1206
1242
if (!zend_is_compiling ()) {
1207
1243
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 );
1221
1249
}
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 ;
1225
1262
}
1226
- zend_string_release (ns_name );
1227
- zend_string_release (scoped_name );
1228
1263
}
1229
1264
}
1230
1265
0 commit comments