diff --git a/Zend/zend_API.c b/Zend/zend_API.c index e58e331773d..7d16e376c3d 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -2581,6 +2581,7 @@ ZEND_API zend_class_entry *zend_register_internal_interface(zend_class_entry *or ZEND_API int zend_register_class_alias_ex(const char *name, size_t name_len, zend_class_entry *ce, int persistent) /* {{{ */ { zend_string *lcname; + zval zv, *ret; /* TODO: Move this out of here in 7.4. */ if (persistent && EG(current_module) && EG(current_module)->type == MODULE_TEMPORARY) { @@ -2598,9 +2599,11 @@ ZEND_API int zend_register_class_alias_ex(const char *name, size_t name_len, zen zend_assert_valid_class_name(lcname); lcname = zend_new_interned_string(lcname); - ce = zend_hash_add_ptr(CG(class_table), lcname, ce); + + ZVAL_ALIAS_PTR(&zv, ce); + ret = zend_hash_add(CG(class_table), lcname, &zv); zend_string_release_ex(lcname, 0); - if (ce) { + if (ret) { if (!(ce->ce_flags & ZEND_ACC_IMMUTABLE)) { ce->refcount++; } diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 3ff94eb574c..e32538591b6 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -541,6 +541,7 @@ struct _zend_ast_ref { /* internal types */ #define IS_INDIRECT 15 #define IS_PTR 16 +#define IS_ALIAS_PTR 17 #define _IS_ERROR 17 /* used for casts */ @@ -1075,6 +1076,11 @@ static zend_always_inline uint32_t zval_gc_info(uint32_t gc_type_info) { Z_TYPE_INFO_P(z) = IS_PTR; \ } while (0) +#define ZVAL_ALIAS_PTR(z, p) do { \ + Z_PTR_P(z) = (p); \ + Z_TYPE_INFO_P(z) = IS_ALIAS_PTR; \ + } while (0) + #define ZVAL_ERROR(z) do { \ Z_TYPE_INFO_P(z) = _IS_ERROR; \ } while (0) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index e46f3c48c75..5f19a90cdee 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -3323,7 +3323,7 @@ static void preload_move_user_classes(HashTable *src, HashTable *dst) } } if (copy) { - _zend_hash_append_ptr(dst, p->key, ce); + _zend_hash_append(dst, p->key, &p->val); } else { orig_dtor(&p->val); } @@ -4332,7 +4332,7 @@ static void preload_load(void) Bucket *end = p + ZCSG(preload_script)->script.class_table.nNumUsed; for (; p != end; p++) { - _zend_hash_append_ptr_ex(CG(class_table), p->key, Z_PTR(p->val), 1); + _zend_hash_append_ex(CG(class_table), p->key, &p->val, 1); } } diff --git a/ext/opcache/tests/preload_class_alias_2.inc b/ext/opcache/tests/preload_class_alias_2.inc new file mode 100644 index 00000000000..3d0a70d8822 --- /dev/null +++ b/ext/opcache/tests/preload_class_alias_2.inc @@ -0,0 +1,4 @@ + +--FILE-- + +--EXPECT-- +bool(true) +bool(true) diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index a6bc78a6447..e78e3cbfce4 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -1080,8 +1080,11 @@ static void zend_accel_persist_class_table(HashTable *class_table) zend_accel_store_interned_string(p->key); zend_persist_class_entry(&p->val); } ZEND_HASH_FOREACH_END(); - ZEND_HASH_FOREACH_PTR(class_table, ce) { - zend_update_parent_ce(ce); + ZEND_HASH_FOREACH_BUCKET(class_table, p) { + if (EXPECTED(Z_TYPE(p->val) != IS_ALIAS_PTR)) { + ce = Z_PTR(p->val); + zend_update_parent_ce(ce); + } } ZEND_HASH_FOREACH_END(); }