Skip to content

Commit f2c8b61

Browse files
committed
Merge branch 'PHP-5.6'
2 parents fd5a756 + 56f9dc2 commit f2c8b61

File tree

3 files changed

+43
-5
lines changed

3 files changed

+43
-5
lines changed

Zend/tests/bug69174.phpt

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
Bug #69174 (leaks when unused inner class use traits precedence)
3+
--FILE--
4+
<?php
5+
function test() {
6+
class C1 {
7+
use T1, T2 {
8+
T1::foo insteadof T2;
9+
T1::bar insteadof T2;
10+
}
11+
}
12+
}
13+
?>
14+
==DONE==
15+
--EXPECT--
16+
==DONE==

Zend/zend_inheritance.c

+21-4
Original file line numberDiff line numberDiff line change
@@ -1268,15 +1268,16 @@ static void zend_traits_init_trait_structures(zend_class_entry *ce) /* {{{ */
12681268
j = 0;
12691269
while (cur_precedence->exclude_from_classes[j].class_name) {
12701270
zend_string* class_name = cur_precedence->exclude_from_classes[j].class_name;
1271+
zend_class_entry *trait;
12711272

1272-
if (!(cur_precedence->exclude_from_classes[j].ce = zend_fetch_class(class_name, ZEND_FETCH_CLASS_TRAIT |ZEND_FETCH_CLASS_NO_AUTOLOAD))) {
1273+
if (!(trait = zend_fetch_class(class_name, ZEND_FETCH_CLASS_TRAIT |ZEND_FETCH_CLASS_NO_AUTOLOAD))) {
12731274
zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", class_name->val);
12741275
}
1275-
zend_check_trait_usage(ce, cur_precedence->exclude_from_classes[j].ce);
1276+
zend_check_trait_usage(ce, trait);
12761277

12771278
/* make sure that the trait method is not from a class mentioned in
12781279
exclude_from_classes, for consistency */
1279-
if (cur_precedence->trait_method->ce == cur_precedence->exclude_from_classes[j].ce) {
1280+
if (cur_precedence->trait_method->ce == trait) {
12801281
zend_error_noreturn(E_COMPILE_ERROR,
12811282
"Inconsistent insteadof definition. "
12821283
"The method %s is to be used from %s, but %s is also on the exclude list",
@@ -1285,6 +1286,7 @@ static void zend_traits_init_trait_structures(zend_class_entry *ce) /* {{{ */
12851286
cur_precedence->trait_method->ce->name->val);
12861287
}
12871288

1289+
cur_precedence->exclude_from_classes[j].ce = trait;
12881290
zend_string_release(class_name);
12891291
j++;
12901292
}
@@ -1358,18 +1360,22 @@ static void zend_do_traits_method_binding(zend_class_entry *ce) /* {{{ */
13581360
for (i = 0; i < ce->num_traits; i++) {
13591361
if (ce->trait_precedences) {
13601362
HashTable exclude_table;
1363+
zend_trait_precedence **precedences;
13611364

13621365
/* TODO: revisit this start size, may be its not optimal */
13631366
zend_hash_init_ex(&exclude_table, 8, NULL, NULL, 0, 0);
13641367

1365-
zend_traits_compile_exclude_table(&exclude_table, ce->trait_precedences, ce->traits[i]);
1368+
precedences = ce->trait_precedences;
1369+
ce->trait_precedences = NULL;
1370+
zend_traits_compile_exclude_table(&exclude_table, precedences, ce->traits[i]);
13661371

13671372
/* copies functions, applies defined aliasing, and excludes unused trait methods */
13681373
ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->traits[i]->function_table, key, fn) {
13691374
zend_traits_copy_functions(key, fn, ce, &overriden, &exclude_table);
13701375
} ZEND_HASH_FOREACH_END();
13711376

13721377
zend_hash_destroy(&exclude_table);
1378+
ce->trait_precedences = precedences;
13731379
} else {
13741380
ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->traits[i]->function_table, key, fn) {
13751381
zend_traits_copy_functions(key, fn, ce, &overriden, NULL);
@@ -1381,6 +1387,17 @@ static void zend_do_traits_method_binding(zend_class_entry *ce) /* {{{ */
13811387
zend_fixup_trait_method(fn, ce);
13821388
} ZEND_HASH_FOREACH_END();
13831389

1390+
if (ce->trait_precedences) {
1391+
i = 0;
1392+
while (ce->trait_precedences[i]) {
1393+
if (ce->trait_precedences[i]->exclude_from_classes) {
1394+
efree(ce->trait_precedences[i]->exclude_from_classes);
1395+
ce->trait_precedences[i]->exclude_from_classes = NULL;
1396+
}
1397+
i++;
1398+
}
1399+
}
1400+
13841401
if (overriden) {
13851402
zend_hash_destroy(overriden);
13861403
FREE_HASHTABLE(overriden);

Zend/zend_opcode.c

+6-1
Original file line numberDiff line numberDiff line change
@@ -221,9 +221,14 @@ void _destroy_zend_class_traits_info(zend_class_entry *ce)
221221
efree(ce->trait_precedences[i]->trait_method);
222222

223223
if (ce->trait_precedences[i]->exclude_from_classes) {
224+
size_t j = 0;
225+
zend_trait_precedence *cur_precedence = ce->trait_precedences[i];
226+
while (cur_precedence->exclude_from_classes[j].class_name) {
227+
zend_string_release(cur_precedence->exclude_from_classes[j].class_name);
228+
j++;
229+
}
224230
efree(ce->trait_precedences[i]->exclude_from_classes);
225231
}
226-
227232
efree(ce->trait_precedences[i]);
228233
i++;
229234
}

0 commit comments

Comments
 (0)