Skip to content

Commit 040002e

Browse files
committed
Fix persisting of inherited class constants
Class constants are inherited to user classes without cloning. Avoid persisting them to shm multiple times. Furthermore, internal class constants should not be persisted at all. Simply keep pointing to the internal class constant. Fixes GH-14109
1 parent 8c8287a commit 040002e

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

ext/opcache/zend_persist.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -923,7 +923,18 @@ zend_class_entry *zend_persist_class_entry(zend_class_entry *orig_ce)
923923
ZEND_HASH_MAP_FOREACH_BUCKET(&ce->constants_table, p) {
924924
ZEND_ASSERT(p->key != NULL);
925925
zend_accel_store_interned_string(p->key);
926-
zend_persist_class_constant(&p->val);
926+
927+
zend_class_constant *c = Z_PTR(p->val);
928+
if (c->ce == orig_ce) {
929+
zend_persist_class_constant(&p->val);
930+
} else {
931+
c = zend_shared_alloc_get_xlat_entry(c);
932+
if (c) {
933+
Z_PTR(p->val) = c;
934+
} else {
935+
/* Internal class constant, keep the pointer to the old one. */
936+
}
937+
}
927938
} ZEND_HASH_FOREACH_END();
928939
HT_FLAGS(&ce->constants_table) &= (HASH_FLAG_UNINITIALIZED | HASH_FLAG_STATIC_KEYS);
929940

ext/opcache/zend_persist_calc.c

Lines changed: 6 additions & 1 deletion
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)
@@ -451,7 +452,11 @@ void zend_persist_class_entry_calc(zend_class_entry *ce)
451452
ZEND_HASH_MAP_FOREACH_BUCKET(&ce->constants_table, p) {
452453
ZEND_ASSERT(p->key != NULL);
453454
ADD_INTERNED_STRING(p->key);
454-
zend_persist_class_constant_calc(&p->val);
455+
456+
zend_class_constant *c = Z_PTR(p->val);
457+
if (c->ce == ce) {
458+
zend_persist_class_constant_calc(&p->val);
459+
}
455460
} ZEND_HASH_FOREACH_END();
456461

457462
zend_hash_persist_calc(&ce->properties_info);

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)