Skip to content

Commit

Permalink
Fixes #61506 (insteadof causes memory leak for unbound classes)
Browse files Browse the repository at this point in the history
Signed-off-by: Stefan Marr <git@stefan-marr.de>
  • Loading branch information
smarr committed Apr 21, 2012
1 parent 9a22bc2 commit d3b86b8
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 2 deletions.
17 changes: 17 additions & 0 deletions Zend/tests/traits/bug61506.phpt
@@ -0,0 +1,17 @@
--TEST--
Bug #61506 (insteadof causes memory leak for unbound classes)
--FILE--
<?php
if (false) {
/** class is never bound */
class A {
use b2, b33 {
b2::b444 insteadof b33;
b2::b444 as b5555;
}
}
}

echo 'DONE';
--EXPECT--
DONE
1 change: 1 addition & 0 deletions Zend/zend.h
Expand Up @@ -436,6 +436,7 @@ struct _zend_trait_precedence {
zend_trait_method_reference *trait_method;

zend_class_entry** exclude_from_classes;
zend_bool exclude_list_contains_strings;

union _zend_function* function;
};
Expand Down
2 changes: 2 additions & 0 deletions Zend/zend_compile.c
Expand Up @@ -3964,6 +3964,7 @@ static void zend_traits_init_trait_structures(zend_class_entry *ce TSRMLS_DC) /*
while ((cur_precedence = ce->trait_precedences[i])) {
/** Resolve classes for all precedence operations. */
if (cur_precedence->exclude_from_classes) {
cur_precedence->exclude_list_contains_strings = 0;
cur_method_ref = cur_precedence->trait_method;
cur_precedence->trait_method->ce = zend_fetch_class(cur_method_ref->class_name,
cur_method_ref->cname_len, ZEND_FETCH_CLASS_TRAIT TSRMLS_CC);
Expand Down Expand Up @@ -4484,6 +4485,7 @@ void zend_prepare_trait_precedence(znode *result, znode *method_reference, znode

trait_precedence->trait_method = (zend_trait_method_reference*)method_reference->u.op.ptr;
trait_precedence->exclude_from_classes = (zend_class_entry**) trait_list->u.op.ptr;
trait_precedence->exclude_list_contains_strings = 1;

trait_precedence->function = NULL;

Expand Down
17 changes: 15 additions & 2 deletions Zend/zend_opcode.c
Expand Up @@ -214,12 +214,15 @@ ZEND_API int zend_cleanup_class_data(zend_class_entry **pce TSRMLS_DC)

void _destroy_zend_class_traits_info(zend_class_entry *ce)
{
size_t i;
size_t j;

if (ce->num_traits > 0 && ce->traits) {
efree(ce->traits);
}

if (ce->trait_aliases) {
size_t i = 0;
i = 0;
while (ce->trait_aliases[i]) {
if (ce->trait_aliases[i]->trait_method) {
if (ce->trait_aliases[i]->trait_method->method_name) {
Expand All @@ -243,14 +246,24 @@ void _destroy_zend_class_traits_info(zend_class_entry *ce)
}

if (ce->trait_precedences) {
size_t i = 0;
i = 0;

while (ce->trait_precedences[i]) {
efree((char*)ce->trait_precedences[i]->trait_method->method_name);
efree((char*)ce->trait_precedences[i]->trait_method->class_name);
efree(ce->trait_precedences[i]->trait_method);

if (ce->trait_precedences[i]->exclude_from_classes) {
/** this is only the case when a class definition was parsed
but the execution never came to the opcodes binding the
implementation */
if (ce->trait_precedences[i]->exclude_list_contains_strings) {
j = 0;
while (ce->trait_precedences[i]->exclude_from_classes[j]) {
str_efree(ce->trait_precedences[i]->exclude_from_classes[j]);
j++;
}
}
efree(ce->trait_precedences[i]->exclude_from_classes);
}

Expand Down

0 comments on commit d3b86b8

Please sign in to comment.