diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2019-10-21 12:17:43 +0200 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2019-10-21 12:17:43 +0200 |
commit | d927b745d6c341053f90145e9781d82eb1b9922b (patch) | |
tree | b072ec54b850c726944576d8d79f8d9dc4fbd782 /Zend | |
parent | 065d00f241d452a888ad187260718e46e331db30 (diff) | |
parent | 3d55386aa895d483dafdb1b4e1870b552dba7b31 (diff) | |
download | php-git-d927b745d6c341053f90145e9781d82eb1b9922b.tar.gz |
Merge branch 'PHP-7.4'
* PHP-7.4:
Fix static prop cleanup for dl'ed internal classes
Diffstat (limited to 'Zend')
-rw-r--r-- | Zend/tests/bug78335_2.phpt | 2 | ||||
-rw-r--r-- | Zend/zend_opcode.c | 48 |
2 files changed, 36 insertions, 14 deletions
diff --git a/Zend/tests/bug78335_2.phpt b/Zend/tests/bug78335_2.phpt index bc9e8f5f0c..5fb5fcb788 100644 --- a/Zend/tests/bug78335_2.phpt +++ b/Zend/tests/bug78335_2.phpt @@ -1,5 +1,7 @@ --TEST-- 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-- <?php diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 54886a3d07..626eacd35d 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -152,22 +152,42 @@ ZEND_API void zend_cleanup_internal_class_data(zend_class_entry *ce) zval *static_members = CE_STATIC_MEMBERS(ce); zval *p = static_members; zval *end = p + ce->default_static_members_count; - - ZEND_MAP_PTR_SET(ce->static_members_table, NULL); - 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(); + 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); + 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); + p++; } - i_zval_ptr_dtor(p); - p++; + efree(static_members); } - efree(static_members); } } |