From b702ad14c958befe6b2e9914959d88fa955d989d Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 14 Jul 2020 15:24:58 +0200 Subject: [PATCH] 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. --- ext/opcache/zend_persist.c | 29 ++++++++++++++++++----------- ext/opcache/zend_persist_calc.c | 28 +++++++++++++--------------- 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index b37504c4b0..f4400b07d4 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -718,19 +718,13 @@ static void zend_persist_class_method(zval *zv) } } -static void zend_persist_property_info(zval *zv) +static zend_property_info *zend_persist_property_info(zend_property_info *prop) { - zend_property_info *prop = zend_shared_alloc_get_xlat_entry(Z_PTR_P(zv)); zend_class_entry *ce; - - if (prop) { - Z_PTR_P(zv) = prop; - return; - } if (ZCG(is_immutable_class)) { - prop = Z_PTR_P(zv) = zend_shared_memdup_put(Z_PTR_P(zv), sizeof(zend_property_info)); + prop = zend_shared_memdup_put(prop, sizeof(zend_property_info)); } else { - prop = Z_PTR_P(zv) = zend_shared_memdup_arena_put(Z_PTR_P(zv), sizeof(zend_property_info)); + prop = zend_shared_memdup_arena_put(prop, sizeof(zend_property_info)); } ce = zend_shared_alloc_get_xlat_entry(prop->ce); if (ce) { @@ -752,6 +746,7 @@ static void zend_persist_property_info(zval *zv) prop->attributes = zend_persist_attributes(prop->attributes); } zend_persist_type(&prop->type); + return prop; } static void zend_persist_class_constant(zval *zv) @@ -798,7 +793,7 @@ static void zend_persist_class_constant(zval *zv) static void zend_persist_class_entry(zval *zv) { Bucket *p; - zend_class_entry *ce = Z_PTR_P(zv); + zend_class_entry *orig_ce = Z_PTR_P(zv), *ce = orig_ce; if (ce->type == ZEND_USER_CLASS) { /* The same zend_class_entry may be reused by class_alias */ @@ -884,9 +879,21 @@ static void zend_persist_class_entry(zval *zv) } zend_hash_persist(&ce->properties_info); ZEND_HASH_FOREACH_BUCKET(&ce->properties_info, p) { + zend_property_info *prop = Z_PTR(p->val); ZEND_ASSERT(p->key != NULL); zend_accel_store_interned_string(p->key); - zend_persist_property_info(&p->val); + if (prop->ce == orig_ce) { + Z_PTR(p->val) = zend_persist_property_info(prop); + } else { + prop = zend_shared_alloc_get_xlat_entry(prop); + if (prop) { + Z_PTR(p->val) = prop; + } else { + /* This can happen if preloading is used and we inherit a property from an + * internal class. In that case we should keep pointing to the internal + * property, without any adjustments. */ + } + } } ZEND_HASH_FOREACH_END(); HT_FLAGS(&ce->properties_info) &= (HASH_FLAG_UNINITIALIZED | HASH_FLAG_STATIC_KEYS); diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index e184b03e77..7e43fc83c0 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -339,21 +339,16 @@ static void zend_persist_class_method_calc(zval *zv) } } -static void zend_persist_property_info_calc(zval *zv) +static void zend_persist_property_info_calc(zend_property_info *prop) { - zend_property_info *prop = Z_PTR_P(zv); - - if (!zend_shared_alloc_get_xlat_entry(prop)) { - zend_shared_alloc_register_xlat_entry(prop, prop); - ADD_SIZE_EX(sizeof(zend_property_info)); - ADD_INTERNED_STRING(prop->name); - zend_persist_type_calc(&prop->type); - if (ZCG(accel_directives).save_comments && prop->doc_comment) { - ADD_STRING(prop->doc_comment); - } - if (prop->attributes) { - zend_persist_attributes_calc(prop->attributes); - } + ADD_SIZE_EX(sizeof(zend_property_info)); + ADD_INTERNED_STRING(prop->name); + zend_persist_type_calc(&prop->type); + if (ZCG(accel_directives).save_comments && prop->doc_comment) { + ADD_STRING(prop->doc_comment); + } + if (prop->attributes) { + zend_persist_attributes_calc(prop->attributes); } } @@ -462,9 +457,12 @@ static void zend_persist_class_entry_calc(zval *zv) zend_hash_persist_calc(&ce->properties_info); ZEND_HASH_FOREACH_BUCKET(&ce->properties_info, p) { + zend_property_info *prop = Z_PTR(p->val); ZEND_ASSERT(p->key != NULL); ADD_INTERNED_STRING(p->key); - zend_persist_property_info_calc(&p->val); + if (prop->ce == ce) { + zend_persist_property_info_calc(prop); + } } ZEND_HASH_FOREACH_END(); if (ce->properties_info_table) { -- 2.50.1