]> granicus.if.org Git - php/commitdiff
Fixed bug #69174 (leaks when unused inner class use traits precedence)
authorXinchen Hui <laruence@php.net>
Thu, 5 Mar 2015 10:16:39 +0000 (18:16 +0800)
committerXinchen Hui <laruence@php.net>
Thu, 5 Mar 2015 10:39:50 +0000 (18:39 +0800)
NEWS
Zend/tests/bug69174.phpt [new file with mode: 0644]
Zend/zend_compile.c
Zend/zend_opcode.c
Zend/zend_signal.c

diff --git a/NEWS b/NEWS
index 5eec926c32cb77244666df6f99c75db4ff4d8980..2c66055e423b7e2d23d9b14cc26aaaa0b4dc1bc8 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,8 @@ PHP                                                                        NEWS
 ?? ??? 2015, PHP 5.5.23
 
 - Core:
+  . Fixed bug #69174 (leaks when unused inner class use traits precedence).
+    (Laruence)
   . Fixed bug #69139 (Crash in gc_zval_possible_root on unserialize).
     (Laruence)
   . Fixed bug #69121 (Segfault in get_current_user when script owner is not
diff --git a/Zend/tests/bug69174.phpt b/Zend/tests/bug69174.phpt
new file mode 100644 (file)
index 0000000..eec0957
--- /dev/null
@@ -0,0 +1,16 @@
+--TEST--
+Bug #69174 (leaks when unused inner class use traits precedence)
+--FILE--
+<?php
+function test() {
+       class C1 {
+               use T1, T2 {
+                       T1::foo insteadof T2;
+                       T1::bar insteadof T2;
+               }
+       }
+}
+?>
+==DONE==
+--EXPECT--
+==DONE==
index 1b0ba89eff596e22f5d9c65e782062775cc57401..edd45bfccc9c4f9b3e124e2df894b04fd37f6f5c 100644 (file)
@@ -4204,16 +4204,20 @@ static void zend_do_traits_method_binding(zend_class_entry *ce TSRMLS_DC) /* {{{
        for (i = 0; i < ce->num_traits; i++) {
                if (ce->trait_precedences) {
                        HashTable exclude_table;
+                       zend_trait_precedence **precedences;
 
                        /* TODO: revisit this start size, may be its not optimal */
                        zend_hash_init_ex(&exclude_table, 2, NULL, NULL, 0, 0);
 
-                       zend_traits_compile_exclude_table(&exclude_table, ce->trait_precedences, ce->traits[i]);
+                       precedences = ce->trait_precedences;
+                       ce->trait_precedences = NULL;
+                       zend_traits_compile_exclude_table(&exclude_table, precedences, ce->traits[i]);
 
                        /* copies functions, applies defined aliasing, and excludes unused trait methods */
                        zend_hash_apply_with_arguments(&ce->traits[i]->function_table TSRMLS_CC, (apply_func_args_t)zend_traits_copy_functions, 3, ce, &overriden, &exclude_table);
 
                        zend_hash_destroy(&exclude_table);
+                       ce->trait_precedences = precedences;
                } else {
                        zend_hash_apply_with_arguments(&ce->traits[i]->function_table TSRMLS_CC, (apply_func_args_t)zend_traits_copy_functions, 3, ce, &overriden, NULL);
                }
@@ -4221,6 +4225,17 @@ static void zend_do_traits_method_binding(zend_class_entry *ce TSRMLS_DC) /* {{{
 
     zend_hash_apply_with_argument(&ce->function_table, (apply_func_arg_t)zend_fixup_trait_method, ce TSRMLS_CC);
 
+       if (ce->trait_precedences) {
+               i = 0;
+               while (ce->trait_precedences[i]) {
+                       if (ce->trait_precedences[i]->exclude_from_classes) {
+                               efree(ce->trait_precedences[i]->exclude_from_classes);
+                               ce->trait_precedences[i]->exclude_from_classes = NULL;
+                       }
+                       i++;
+               }
+       }
+
        if (overriden) {
                zend_hash_destroy(overriden);
                FREE_HASHTABLE(overriden);
index e03cf3073eaee1279369ec814a72b9a423e0c180..b8e850d629de7573b77fae6ffc2fd2533a1f4e58 100644 (file)
@@ -256,9 +256,14 @@ void _destroy_zend_class_traits_info(zend_class_entry *ce)
                        efree(ce->trait_precedences[i]->trait_method);
 
                        if (ce->trait_precedences[i]->exclude_from_classes) {
+                               zend_uint j = 0;
+                               zend_trait_precedence *cur_precedence = ce->trait_precedences[i];
+                               while (cur_precedence->exclude_from_classes[j]) {
+                                       efree(cur_precedence->exclude_from_classes[j]);
+                                       j++;
+                               }
                                efree(ce->trait_precedences[i]->exclude_from_classes);
                        }
-
                        efree(ce->trait_precedences[i]);
                        i++;
                }
index 6105fb11193b4b69a411394b115449b369abcdce..3e0ce642136264f6be9df909cda50a0e23018ce5 100644 (file)
@@ -78,8 +78,8 @@ void zend_signal_handler_defer(int signo, siginfo_t *siginfo, void *context)
 
        if (SIGG(active)) {
                if (SIGG(depth) == 0) { /* try to handle signal */
-                       if (SIGG(blocked) != -1) { /* inverse */
-                               SIGG(blocked) = -1; /* signal is not blocked */
+                       if (SIGG(blocked) != 0) { /* inverse */
+                               SIGG(blocked) = 0; /* signal is not blocked */
                        }
                        if (SIGG(running) == 0) {
                                SIGG(running) = 1;
@@ -99,7 +99,7 @@ void zend_signal_handler_defer(int signo, siginfo_t *siginfo, void *context)
                                SIGG(running) = 0;
                        }
                } else { /* delay signal handling */
-                       SIGG(blocked) = 0; /* signal is blocked */
+                       SIGG(blocked) = 1; /* signal is blocked */
 
                        if ((queue = SIGG(pavail))) { /* if none available it's simply forgotton */
                                SIGG(pavail) = queue->next;
@@ -314,7 +314,7 @@ void zend_signal_deactivate(TSRMLS_D)
        SIGNAL_BEGIN_CRITICAL();
        SIGG(active) = 0;
        SIGG(running) = 0;
-       SIGG(blocked) = -1;
+       SIGG(blocked) = 0;
        SIGG(depth) = 0;
        SIGNAL_END_CRITICAL();
 }