From 7dce0194c815cdc75a780b6471660042aed7bd7a Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Thu, 21 Mar 2013 21:09:30 +0800 Subject: Fixed bug #64239 (Debug backtrace changed behavior since 5.4.10 or 5.4.11) --- NEWS | 2 ++ Zend/tests/bug64239_1.phpt | 26 +++++++++++-------- Zend/tests/bug64239_2.phpt | 58 +++++++++++++++++++++++++++++++++++++++++++ Zend/tests/bug64239_3.phpt | 33 ++++++++++++++++++++++++ Zend/tests/bug64239_4.phpt | 31 +++++++++++++++++++++++ Zend/zend_API.c | 56 +++++++++++++++++++++++++++++++++++++++++ Zend/zend_API.h | 3 +++ Zend/zend_builtin_functions.c | 20 ++++++++++++--- 8 files changed, 216 insertions(+), 13 deletions(-) create mode 100644 Zend/tests/bug64239_2.phpt create mode 100644 Zend/tests/bug64239_3.phpt create mode 100644 Zend/tests/bug64239_4.phpt 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-- 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-- +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-- +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-- + +--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); -- cgit v1.2.1