Fix static prop cleanup for dl'ed internal classes

This commit is contained in:
Nikita Popov 2019-10-21 11:30:00 +02:00
parent ed31e04133
commit 3d55386aa8
2 changed files with 36 additions and 14 deletions

View file

@ -1,5 +1,7 @@
--TEST-- --TEST--
Bug #78335: Static properties containing cycles report as leak (internal class variant) Bug #78335: Static properties containing cycles report as leak (internal class variant)
--SKIPIF--
<?php if (!extension_loaded("zend-test")) die("skip requires zend-test"); ?>
--FILE-- --FILE--
<?php <?php

View file

@ -152,7 +152,26 @@ ZEND_API void zend_cleanup_internal_class_data(zend_class_entry *ce)
zval *static_members = CE_STATIC_MEMBERS(ce); zval *static_members = CE_STATIC_MEMBERS(ce);
zval *p = static_members; zval *p = static_members;
zval *end = p + ce->default_static_members_count; zval *end = p + ce->default_static_members_count;
if (UNEXPECTED(ZEND_MAP_PTR(ce->static_members_table) == &ce->default_static_members_table)) {
/* Special case: If this is a static property on a dl'ed internal class, then the
* static property table and the default property table are the same. In this case we
* destroy the values here, but leave behind valid UNDEF zvals and don't free the
* table itself. */
while (p != end) {
if (UNEXPECTED(Z_ISREF_P(p))) {
zend_property_info *prop_info;
ZEND_REF_FOREACH_TYPE_SOURCES(Z_REF_P(p), prop_info) {
if (prop_info->ce == ce && p - static_members == prop_info->offset) {
ZEND_REF_DEL_TYPE_SOURCE(Z_REF_P(p), prop_info);
break; /* stop iteration here, the array might be realloc()'ed */
}
} ZEND_REF_FOREACH_TYPE_SOURCES_END();
}
i_zval_ptr_dtor(p);
ZVAL_UNDEF(p);
p++;
}
} else {
ZEND_MAP_PTR_SET(ce->static_members_table, NULL); ZEND_MAP_PTR_SET(ce->static_members_table, NULL);
while (p != end) { while (p != end) {
if (UNEXPECTED(Z_ISREF_P(p))) { if (UNEXPECTED(Z_ISREF_P(p))) {
@ -169,6 +188,7 @@ ZEND_API void zend_cleanup_internal_class_data(zend_class_entry *ce)
} }
efree(static_members); efree(static_members);
} }
}
} }
static void _destroy_zend_class_traits_info(zend_class_entry *ce) static void _destroy_zend_class_traits_info(zend_class_entry *ce)