summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXinchen Hui <laruence@php.net>2013-03-21 21:09:30 +0800
committerXinchen Hui <laruence@php.net>2013-03-21 21:09:30 +0800
commit7dce0194c815cdc75a780b6471660042aed7bd7a (patch)
treed1413ee4ced418436ebaa01f9276347e6a21e58a
parent08624ea90d9178679cdbb553de0170f2fd7ac09c (diff)
downloadphp-git-7dce0194c815cdc75a780b6471660042aed7bd7a.tar.gz
Fixed bug #64239 (Debug backtrace changed behavior since 5.4.10 or 5.4.11)
-rw-r--r--NEWS2
-rw-r--r--Zend/tests/bug64239_1.phpt26
-rw-r--r--Zend/tests/bug64239_2.phpt58
-rw-r--r--Zend/tests/bug64239_3.phpt33
-rw-r--r--Zend/tests/bug64239_4.phpt31
-rw-r--r--Zend/zend_API.c56
-rw-r--r--Zend/zend_API.h3
-rw-r--r--Zend/zend_builtin_functions.c20
8 files changed, 216 insertions, 13 deletions
diff --git a/NEWS b/NEWS
index d60fcb3517..bc132d4633 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,8 @@ PHP NEWS
(Dmitry)
. Fixed bug #64370 (microtime(true) less than $_SERVER['REQUEST_TIME_FLOAT']).
(Anatol)
+ . Fixed bug #64239 (Debug backtrace changed behavior since 5.4.10 or 5.4.11).
+ (Dmitry, Laruence)
. Fixed bug #63976 (Parent class incorrectly using child constant in class
property). (Dmitry)
. Fixed bug #62343 (Show class_alias In get_declared_classes()) (Dmitry)
diff --git a/Zend/tests/bug64239_1.phpt b/Zend/tests/bug64239_1.phpt
index fe58cbd767..10d44c1817 100644
--- a/Zend/tests/bug64239_1.phpt
+++ b/Zend/tests/bug64239_1.phpt
@@ -3,20 +3,26 @@ Bug #64239 (get_class_methods() changed behavior)
--FILE--
<?php
class A {
- public function test() { $this->backtrace(); }
-}
-class B {
use T2 { t2method as Bmethod; }
}
+
+class B extends A {
+}
+
trait T2 {
public function t2method() {
}
}
-var_dump(get_class_methods("B"));
+print_r(get_class_methods("A"));
+print_r(get_class_methods("B"));
--EXPECT--
-array(2) {
- [0]=>
- string(7) "bmethod"
- [1]=>
- string(8) "t2method"
-}
+Array
+(
+ [0] => Bmethod
+ [1] => t2method
+)
+Array
+(
+ [0] => Bmethod
+ [1] => t2method
+)
diff --git a/Zend/tests/bug64239_2.phpt b/Zend/tests/bug64239_2.phpt
new file mode 100644
index 0000000000..26cf8ee1af
--- /dev/null
+++ b/Zend/tests/bug64239_2.phpt
@@ -0,0 +1,58 @@
+--TEST--
+Bug #64239 (debug_backtrace() changed behavior)
+--FILE--
+<?php
+class A {
+ use T1;
+ public function test() { $this->backtrace(); }
+}
+
+class B {
+ use T2 { t2method as Bmethod; }
+}
+
+class C extends A {
+}
+
+trait T1 {
+ protected function backtrace() {
+ $b = new B();
+ $b->Bmethod();
+ }
+}
+trait T2 {
+ public function t2method() {
+ print_r(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1));
+ }
+}
+$a = new A();
+$a->test();
+
+$c = new C();
+$c->test();
+?>
+--EXPECTF--
+Array
+(
+ [0] => Array
+ (
+ [file] => %sbug64239_2.php
+ [line] => %d
+ [function] => Bmethod
+ [class] => B
+ [type] => ->
+ )
+
+)
+Array
+(
+ [0] => Array
+ (
+ [file] => %sbug64239_2.php
+ [line] => %d
+ [function] => Bmethod
+ [class] => B
+ [type] => ->
+ )
+
+)
diff --git a/Zend/tests/bug64239_3.phpt b/Zend/tests/bug64239_3.phpt
new file mode 100644
index 0000000000..15faeb9852
--- /dev/null
+++ b/Zend/tests/bug64239_3.phpt
@@ -0,0 +1,33 @@
+--TEST--
+Bug #64239 (debug_print_backtrace() changed behavior)
+--FILE--
+<?php
+class A {
+ use T2 { t2method as Bmethod; }
+}
+
+class C extends A {
+ public function Bmethod() {
+ debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
+ }
+}
+
+trait T2 {
+ public function t2method() {
+ debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
+ }
+}
+
+$a = new A();
+$a->Bmethod();
+$a->t2method();
+
+$c = new C();
+$c->Bmethod();
+$c->t2method();
+?>
+--EXPECTF--
+#0 A->Bmethod() called at [%sbug64239_3.php:%d]
+#0 A->t2method() called at [%sbug64239_3.php:%d]
+#0 C->Bmethod() called at [%sbug64239_3.php:%d]
+#0 A->t2method() called at [%sbug64239_3.php:%d]
diff --git a/Zend/tests/bug64239_4.phpt b/Zend/tests/bug64239_4.phpt
new file mode 100644
index 0000000000..7ab761ef72
--- /dev/null
+++ b/Zend/tests/bug64239_4.phpt
@@ -0,0 +1,31 @@
+--TEST--
+Bug #64239 (debug_print_backtrace() changed behavior)
+--FILE--
+<?php
+class A {
+ use T2 { t2method as Bmethod; }
+}
+
+class C extends A {
+ public static function Bmethod() {
+ debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
+ }
+}
+
+trait T2 {
+ public static function t2method() {
+ debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
+ }
+}
+
+A::Bmethod();
+A::t2method();
+
+C::Bmethod();
+C::t2method();
+?>
+--EXPECTF--
+#0 A::Bmethod() called at [%sbug64239_4.php:%d]
+#0 A::t2method() called at [%sbug64239_4.php:%d]
+#0 C::Bmethod() called at [%sbug64239_4.php:%d]
+#0 A::t2method() called at [%sbug64239_4.php:%d]
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 668ddff39f..529092ab92 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -3913,6 +3913,62 @@ ZEND_API void zend_restore_error_handling(zend_error_handling *saved TSRMLS_DC)
}
/* }}} */
+ZEND_API const char* zend_find_alias_name(zend_class_entry *ce, const char *name, zend_uint len) /* {{{ */
+{
+ zend_trait_alias *alias, **alias_ptr;
+
+ alias_ptr = ce->trait_aliases;
+ alias = *alias_ptr;
+ while (alias) {
+ if (alias->alias_len == len &&
+ !strncasecmp(name, alias->alias, alias->alias_len)) {
+ return alias->alias;
+ }
+ alias_ptr++;
+ alias = *alias_ptr;
+ }
+
+ return name;
+}
+/* }}} */
+
+ZEND_API const char* zend_resolve_method_name(zend_class_entry *ce, zend_function *f) /* {{{ */
+{
+ zend_function *func;
+ HashPosition iterator;
+ HashTable *function_table;
+
+ if (f->common.type != ZEND_USER_FUNCTION ||
+ *(f->op_array.refcount) < 2 ||
+ !f->common.scope ||
+ !f->common.scope->trait_aliases) {
+ return f->common.function_name;
+ }
+
+ function_table = &ce->function_table;
+ zend_hash_internal_pointer_reset_ex(function_table, &iterator);
+ while (zend_hash_get_current_data_ex(function_table, (void **)&func, &iterator) == SUCCESS) {
+ if (func == f) {
+ char *name;
+ uint len;
+ ulong idx;
+
+ if (zend_hash_get_current_key_ex(function_table, &name, &len, &idx, 0, &iterator) != HASH_KEY_IS_STRING) {
+ return f->common.function_name;
+ }
+ --len;
+ if (len == strlen(f->common.function_name) &&
+ !strncasecmp(name, f->common.function_name, len)) {
+ return f->common.function_name;
+ }
+ return zend_find_alias_name(f->common.scope, name, len);
+ }
+ zend_hash_move_forward_ex(function_table, &iterator);
+ }
+ return f->common.function_name;
+}
+/* }}} */
+
/*
* Local variables:
* tab-width: 4
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index e20f8d6240..62bf391ca5 100644
--- a/Zend/zend_API.h
+++ b/Zend/zend_API.h
@@ -517,6 +517,9 @@ ZEND_API void zend_reset_all_cv(HashTable *symbol_table TSRMLS_DC);
ZEND_API void zend_rebuild_symbol_table(TSRMLS_D);
+ZEND_API const char* zend_find_alias_name(zend_class_entry *ce, const char *name, zend_uint len);
+ZEND_API const char* zend_resolve_method_name(zend_class_entry *ce, zend_function *f);
+
#define add_method(arg, key, method) add_assoc_function((arg), (key), (method))
ZEND_API ZEND_FUNCTION(display_disabled_function);
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
index dcb18182e1..f29676bac0 100644
--- a/Zend/zend_builtin_functions.c
+++ b/Zend/zend_builtin_functions.c
@@ -1092,7 +1092,7 @@ ZEND_FUNCTION(get_class_methods)
(len != key_len - 1 ||
!same_name(key, mptr->common.function_name, len))) {
MAKE_STD_ZVAL(method_name);
- ZVAL_STRINGL(method_name, key, key_len - 1, 1);
+ ZVAL_STRINGL(method_name, zend_find_alias_name(mptr->common.scope, key, key_len - 1), key_len - 1, 1);
zend_hash_next_index_insert(return_value->value.ht, &method_name, sizeof(zval *), NULL);
} else {
MAKE_STD_ZVAL(method_name);
@@ -2118,7 +2118,14 @@ ZEND_FUNCTION(debug_print_backtrace)
lineno = 0;
}
- function_name = ptr->function_state.function->common.function_name;
+ function_name = (ptr->function_state.function->common.scope &&
+ ptr->function_state.function->common.scope->trait_aliases) ?
+ zend_resolve_method_name(
+ ptr->object ?
+ Z_OBJCE_P(ptr->object) :
+ ptr->function_state.function->common.scope,
+ ptr->function_state.function) :
+ ptr->function_state.function->common.function_name;
if (function_name) {
if (ptr->object) {
@@ -2299,7 +2306,14 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
filename = NULL;
}
- function_name = ptr->function_state.function->common.function_name;
+ function_name = (ptr->function_state.function->common.scope &&
+ ptr->function_state.function->common.scope->trait_aliases) ?
+ zend_resolve_method_name(
+ ptr->object ?
+ Z_OBJCE_P(ptr->object) :
+ ptr->function_state.function->common.scope,
+ ptr->function_state.function) :
+ ptr->function_state.function->common.function_name;
if (function_name) {
add_assoc_string_ex(stack_frame, "function", sizeof("function"), (char*)function_name, 1);