Commit:    7dce0194c815cdc75a780b6471660042aed7bd7a
Author:    Xinchen Hui <larue...@php.net>         Thu, 21 Mar 2013 21:09:30 
+0800
Parents:   08624ea90d9178679cdbb553de0170f2fd7ac09c
Branches:  PHP-5.4

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=7dce0194c815cdc75a780b6471660042aed7bd7a

Log:
Fixed bug #64239 (Debug backtrace changed behavior since 5.4.10 or 5.4.11)

Bugs:
https://bugs.php.net/64239

Changed paths:
  M  NEWS
  M  Zend/tests/bug64239_1.phpt
  A  Zend/tests/bug64239_2.phpt
  A  Zend/tests/bug64239_3.phpt
  A  Zend/tests/bug64239_4.phpt
  M  Zend/zend_API.c
  M  Zend/zend_API.h
  M  Zend/zend_builtin_functions.c

diff --git a/NEWS b/NEWS
index d60fcb3..bc132d4 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 fe58cbd..10d44c1 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 0000000..26cf8ee
--- /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 0000000..15faeb9
--- /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 0000000..7ab761e
--- /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 668ddff..529092a 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 e20f8d6..62bf391 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 dcb1818..f29676b 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);
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to