]> granicus.if.org Git - php/commitdiff
Fix preloading of union typed property inherited from internal class
authorNikita Popov <nikita.ppv@gmail.com>
Tue, 14 Jul 2020 13:24:58 +0000 (15:24 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Tue, 14 Jul 2020 13:24:58 +0000 (15:24 +0200)
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
ext/opcache/zend_persist_calc.c

index b37504c4b0606974447dbe42db642c7a7a4c95cf..f4400b07d4d3cdae2d1ed45bbb672b07a47607a4 100644 (file)
@@ -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);
 
index e184b03e77def78ff721c7fbc78c102802039d1d..7e43fc83c0c0a584e5d3f96cf396375d09cfca3f 100644 (file)
@@ -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) {