diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index 7513f71db3401..7cc22f9669196 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -806,12 +806,17 @@ static zend_property_info *zend_persist_property_info(zend_property_info *prop) static void zend_persist_class_constant(zval *zv) { - zend_class_constant *c = zend_shared_alloc_get_xlat_entry(Z_PTR_P(zv)); + zend_class_constant *orig_c = Z_PTR_P(zv); + zend_class_constant *c = zend_shared_alloc_get_xlat_entry(orig_c); zend_class_entry *ce; if (c) { Z_PTR_P(zv) = c; return; + } else if (((orig_c->ce->ce_flags & ZEND_ACC_IMMUTABLE) && !(Z_CONSTANT_FLAGS(orig_c->value) & CONST_OWNED)) + || orig_c->ce->type == ZEND_INTERNAL_CLASS) { + /* Class constant comes from a different file in shm or internal class, keep existing pointer. */ + return; } else if (!ZCG(current_persistent_script)->corrupted && zend_accel_in_shm(Z_PTR_P(zv))) { return; diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index c4c5c5fa3ba5f..881f3954c04f3 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -26,6 +26,7 @@ #include "zend_shared_alloc.h" #include "zend_operators.h" #include "zend_attributes.h" +#include "zend_constants.h" #define ADD_DUP_SIZE(m,s) ZCG(current_persistent_script)->size += zend_shared_memdup_size((void*)m, s) #define ADD_SIZE(m) ZCG(current_persistent_script)->size += ZEND_ALIGNED_SIZE(m) @@ -386,6 +387,11 @@ static void zend_persist_class_constant_calc(zval *zv) zend_class_constant *c = Z_PTR_P(zv); if (!zend_shared_alloc_get_xlat_entry(c)) { + if (((c->ce->ce_flags & ZEND_ACC_IMMUTABLE) && !(Z_CONSTANT_FLAGS(c->value) & CONST_OWNED)) + || c->ce->type == ZEND_INTERNAL_CLASS) { + /* Class constant comes from a different file in shm or internal class, keep existing pointer. */ + return; + } if (!ZCG(current_persistent_script)->corrupted && zend_accel_in_shm(Z_PTR_P(zv))) { return; diff --git a/ext/zend_test/tests/gh14109.phpt b/ext/zend_test/tests/gh14109.phpt new file mode 100644 index 0000000000000..be8c5a75a7bc2 --- /dev/null +++ b/ext/zend_test/tests/gh14109.phpt @@ -0,0 +1,16 @@ +--TEST-- +GH-14109: User class extending internal class with attributes +--EXTENSIONS-- +zend_test +--FILE-- +getAttributes() as $attribute) { + var_dump($attribute->newInstance()); +} +?> +--EXPECTF-- +object(ZendTestRepeatableAttribute)#%d (0) { +} +object(ZendTestRepeatableAttribute)#%d (0) { +}