Skip to content

Commit 5009142

Browse files
committed
Fix persisting of inherited class constants
Class constants are inherited to user classes without cloning. Thus, internal class constants should not be persisted at all. Simply keep pointing to the internal class constant. Fixes GH-14109
1 parent 8c8287a commit 5009142

File tree

3 files changed

+28
-1
lines changed

3 files changed

+28
-1
lines changed

ext/opcache/zend_persist.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -806,12 +806,17 @@ static zend_property_info *zend_persist_property_info(zend_property_info *prop)
806806

807807
static void zend_persist_class_constant(zval *zv)
808808
{
809-
zend_class_constant *c = zend_shared_alloc_get_xlat_entry(Z_PTR_P(zv));
809+
zend_class_constant *orig_c = Z_PTR_P(zv);
810+
zend_class_constant *c = zend_shared_alloc_get_xlat_entry(orig_c);
810811
zend_class_entry *ce;
811812

812813
if (c) {
813814
Z_PTR_P(zv) = c;
814815
return;
816+
} else if (((orig_c->ce->ce_flags & ZEND_ACC_IMMUTABLE) && !(Z_CONSTANT_FLAGS(orig_c->value) & CONST_OWNED))
817+
|| orig_c->ce->type == ZEND_INTERNAL_CLASS) {
818+
/* Class constant comes from a different file in shm or internal class, keep existing pointer. */
819+
return;
815820
} else if (!ZCG(current_persistent_script)->corrupted
816821
&& zend_accel_in_shm(Z_PTR_P(zv))) {
817822
return;

ext/opcache/zend_persist_calc.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "zend_shared_alloc.h"
2727
#include "zend_operators.h"
2828
#include "zend_attributes.h"
29+
#include "zend_constants.h"
2930

3031
#define ADD_DUP_SIZE(m,s) ZCG(current_persistent_script)->size += zend_shared_memdup_size((void*)m, s)
3132
#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)
386387
zend_class_constant *c = Z_PTR_P(zv);
387388

388389
if (!zend_shared_alloc_get_xlat_entry(c)) {
390+
if (((c->ce->ce_flags & ZEND_ACC_IMMUTABLE) && !(Z_CONSTANT_FLAGS(c->value) & CONST_OWNED))
391+
|| c->ce->type == ZEND_INTERNAL_CLASS) {
392+
/* Class constant comes from a different file in shm or internal class, keep existing pointer. */
393+
return;
394+
}
389395
if (!ZCG(current_persistent_script)->corrupted
390396
&& zend_accel_in_shm(Z_PTR_P(zv))) {
391397
return;

ext/zend_test/tests/gh14109.phpt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
GH-14109: User class extending internal class with attributes
3+
--EXTENSIONS--
4+
zend_test
5+
--FILE--
6+
<?php
7+
class Test extends ZendAttributeTest {}
8+
foreach ((new ReflectionClassConstant(Test::class, 'TEST_CONST'))->getAttributes() as $attribute) {
9+
var_dump($attribute->newInstance());
10+
}
11+
?>
12+
--EXPECTF--
13+
object(ZendTestRepeatableAttribute)#%d (0) {
14+
}
15+
object(ZendTestRepeatableAttribute)#%d (0) {
16+
}

0 commit comments

Comments
 (0)