Skip to content

Commit b702ad1

Browse files
committed
Fix preloading of union typed property inherited from internal class
Tricky edge case: We inherit a property from an internal class, in which case no property duplication takes place. We should not try to persist the property info in that case. This didn't really matter previously, but now that the property has some non-interned owned data (the type), we need to make sure we don't try to free that.
1 parent 7e6b2e2 commit b702ad1

File tree

2 files changed

+31
-26
lines changed

2 files changed

+31
-26
lines changed

ext/opcache/zend_persist.c

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -718,19 +718,13 @@ static void zend_persist_class_method(zval *zv)
718718
}
719719
}
720720

721-
static void zend_persist_property_info(zval *zv)
721+
static zend_property_info *zend_persist_property_info(zend_property_info *prop)
722722
{
723-
zend_property_info *prop = zend_shared_alloc_get_xlat_entry(Z_PTR_P(zv));
724723
zend_class_entry *ce;
725-
726-
if (prop) {
727-
Z_PTR_P(zv) = prop;
728-
return;
729-
}
730724
if (ZCG(is_immutable_class)) {
731-
prop = Z_PTR_P(zv) = zend_shared_memdup_put(Z_PTR_P(zv), sizeof(zend_property_info));
725+
prop = zend_shared_memdup_put(prop, sizeof(zend_property_info));
732726
} else {
733-
prop = Z_PTR_P(zv) = zend_shared_memdup_arena_put(Z_PTR_P(zv), sizeof(zend_property_info));
727+
prop = zend_shared_memdup_arena_put(prop, sizeof(zend_property_info));
734728
}
735729
ce = zend_shared_alloc_get_xlat_entry(prop->ce);
736730
if (ce) {
@@ -752,6 +746,7 @@ static void zend_persist_property_info(zval *zv)
752746
prop->attributes = zend_persist_attributes(prop->attributes);
753747
}
754748
zend_persist_type(&prop->type);
749+
return prop;
755750
}
756751

757752
static void zend_persist_class_constant(zval *zv)
@@ -798,7 +793,7 @@ static void zend_persist_class_constant(zval *zv)
798793
static void zend_persist_class_entry(zval *zv)
799794
{
800795
Bucket *p;
801-
zend_class_entry *ce = Z_PTR_P(zv);
796+
zend_class_entry *orig_ce = Z_PTR_P(zv), *ce = orig_ce;
802797

803798
if (ce->type == ZEND_USER_CLASS) {
804799
/* The same zend_class_entry may be reused by class_alias */
@@ -884,9 +879,21 @@ static void zend_persist_class_entry(zval *zv)
884879
}
885880
zend_hash_persist(&ce->properties_info);
886881
ZEND_HASH_FOREACH_BUCKET(&ce->properties_info, p) {
882+
zend_property_info *prop = Z_PTR(p->val);
887883
ZEND_ASSERT(p->key != NULL);
888884
zend_accel_store_interned_string(p->key);
889-
zend_persist_property_info(&p->val);
885+
if (prop->ce == orig_ce) {
886+
Z_PTR(p->val) = zend_persist_property_info(prop);
887+
} else {
888+
prop = zend_shared_alloc_get_xlat_entry(prop);
889+
if (prop) {
890+
Z_PTR(p->val) = prop;
891+
} else {
892+
/* This can happen if preloading is used and we inherit a property from an
893+
* internal class. In that case we should keep pointing to the internal
894+
* property, without any adjustments. */
895+
}
896+
}
890897
} ZEND_HASH_FOREACH_END();
891898
HT_FLAGS(&ce->properties_info) &= (HASH_FLAG_UNINITIALIZED | HASH_FLAG_STATIC_KEYS);
892899

ext/opcache/zend_persist_calc.c

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -339,21 +339,16 @@ static void zend_persist_class_method_calc(zval *zv)
339339
}
340340
}
341341

342-
static void zend_persist_property_info_calc(zval *zv)
342+
static void zend_persist_property_info_calc(zend_property_info *prop)
343343
{
344-
zend_property_info *prop = Z_PTR_P(zv);
345-
346-
if (!zend_shared_alloc_get_xlat_entry(prop)) {
347-
zend_shared_alloc_register_xlat_entry(prop, prop);
348-
ADD_SIZE_EX(sizeof(zend_property_info));
349-
ADD_INTERNED_STRING(prop->name);
350-
zend_persist_type_calc(&prop->type);
351-
if (ZCG(accel_directives).save_comments && prop->doc_comment) {
352-
ADD_STRING(prop->doc_comment);
353-
}
354-
if (prop->attributes) {
355-
zend_persist_attributes_calc(prop->attributes);
356-
}
344+
ADD_SIZE_EX(sizeof(zend_property_info));
345+
ADD_INTERNED_STRING(prop->name);
346+
zend_persist_type_calc(&prop->type);
347+
if (ZCG(accel_directives).save_comments && prop->doc_comment) {
348+
ADD_STRING(prop->doc_comment);
349+
}
350+
if (prop->attributes) {
351+
zend_persist_attributes_calc(prop->attributes);
357352
}
358353
}
359354

@@ -462,9 +457,12 @@ static void zend_persist_class_entry_calc(zval *zv)
462457

463458
zend_hash_persist_calc(&ce->properties_info);
464459
ZEND_HASH_FOREACH_BUCKET(&ce->properties_info, p) {
460+
zend_property_info *prop = Z_PTR(p->val);
465461
ZEND_ASSERT(p->key != NULL);
466462
ADD_INTERNED_STRING(p->key);
467-
zend_persist_property_info_calc(&p->val);
463+
if (prop->ce == ce) {
464+
zend_persist_property_info_calc(prop);
465+
}
468466
} ZEND_HASH_FOREACH_END();
469467

470468
if (ce->properties_info_table) {

0 commit comments

Comments
 (0)