summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXinchen Hui <laruence@php.net>2015-03-05 18:16:39 +0800
committerXinchen Hui <laruence@php.net>2015-03-05 18:39:50 +0800
commitf039225597b51f2ee02a050391d497ae68d63b39 (patch)
tree9cb4427f51218a5d5e8ffaa8010f85edb039063a
parent837eeefee9e01156b364a4b0e9cff8d9f0a1a1d5 (diff)
downloadphp-git-f039225597b51f2ee02a050391d497ae68d63b39.tar.gz
Fixed bug #69174 (leaks when unused inner class use traits precedence)
-rw-r--r--NEWS2
-rw-r--r--Zend/tests/bug69174.phpt16
-rw-r--r--Zend/zend_compile.c17
-rw-r--r--Zend/zend_opcode.c7
-rw-r--r--Zend/zend_signal.c8
5 files changed, 44 insertions, 6 deletions
diff --git a/NEWS b/NEWS
index 5eec926c32..2c66055e42 100644
--- 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
index 0000000000..eec0957470
--- /dev/null
+++ b/Zend/tests/bug69174.phpt
@@ -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==
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 1b0ba89eff..edd45bfccc 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -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);
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c
index e03cf3073e..b8e850d629 100644
--- a/Zend/zend_opcode.c
+++ b/Zend/zend_opcode.c
@@ -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++;
}
diff --git a/Zend/zend_signal.c b/Zend/zend_signal.c
index 6105fb1119..3e0ce64213 100644
--- a/Zend/zend_signal.c
+++ b/Zend/zend_signal.c
@@ -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();
}