diff options
-rw-r--r-- | Zend/zend_API.c | 7 | ||||
-rw-r--r-- | Zend/zend_types.h | 6 | ||||
-rw-r--r-- | ext/opcache/ZendAccelerator.c | 4 | ||||
-rw-r--r-- | ext/opcache/tests/preload_class_alias_2.inc | 4 | ||||
-rw-r--r-- | ext/opcache/tests/preload_class_alias_2.phpt | 17 | ||||
-rw-r--r-- | ext/opcache/zend_persist.c | 7 |
6 files changed, 39 insertions, 6 deletions
diff --git a/Zend/zend_API.c b/Zend/zend_API.c index e58e331773..7d16e376c3 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 3ff94eb574..e32538591b 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 e46f3c48c7..5f19a90cde 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 0000000000..3d0a70d882 --- /dev/null +++ b/ext/opcache/tests/preload_class_alias_2.inc @@ -0,0 +1,4 @@ +<?php +interface I {} +class B implements I {} +class_alias('B', 'C'); diff --git a/ext/opcache/tests/preload_class_alias_2.phpt b/ext/opcache/tests/preload_class_alias_2.phpt new file mode 100644 index 0000000000..6dc2c21a8a --- /dev/null +++ b/ext/opcache/tests/preload_class_alias_2.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #78918.2: Class alias during preloading causes assertion failure +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +opcache.preload={PWD}/preload_class_alias_2.inc +--SKIPIF-- +<?php require_once('skipif.inc'); ?> +--FILE-- +<?php +var_dump(class_exists('B')); +var_dump(class_exists('C')); +?> +--EXPECT-- +bool(true) +bool(true) diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index a6bc78a644..e78e3cbfce 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(); } |