From: Dmitry Stogov Date: Wed, 22 Jun 2005 15:24:15 +0000 (+0000) Subject: Fixed bug #29896 (Backtrace argument list out of sync) X-Git-Tag: php-5.0.5RC1~137 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=534385818295cfbcd8cb07faa6dee364c820d37a;p=php Fixed bug #29896 (Backtrace argument list out of sync) --- diff --git a/NEWS b/NEWS index 9b8d9f527e..d5c69d1706 100644 --- a/NEWS +++ b/NEWS @@ -159,6 +159,7 @@ PHP NEWS handler). (Tony) - Fixed bug #29971 (variables_order behaviour). (Dmitry) - Fixed bug #29944 (Function defined in switch, crashes). (Dmitry) +- Fixed bug #29896 (Backtrace argument list out of sync). (Dmitry) - Fixed bug #29683 (headers_list() returns empty array). (Tony) - Fixed bug #29583 (crash when echoing a COM object). (M.Sisolak, Wez) - Fixed bug #29338 (unencoded spaces get ignored after certain tags). (Ilia) diff --git a/Zend/tests/bug29896.phpt b/Zend/tests/bug29896.phpt new file mode 100755 index 0000000000..1e2eb0b067 --- /dev/null +++ b/Zend/tests/bug29896.phpt @@ -0,0 +1,28 @@ +--TEST-- +Bug #29896 (Backtrace argument list out of sync) +--FILE-- + +--EXPECTF-- +#0 userErrorHandler(8, Undefined variable: b, %sbug29896.php, 11, Array ([A1] => Test1)) called at [%sbug29896.php:11] +#1 GenerateError1(Test1) called at [%sbug29896.php:16] +#2 GenerateError2(Test2) called at [%sbug29896.php:19] + diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 7db7816ce3..d5324da41a 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -1551,7 +1551,7 @@ void debug_print_backtrace_args(zval *arg_array TSRMLS_DC) /* {{{ proto void debug_print_backtrace(void) */ ZEND_FUNCTION(debug_print_backtrace) { - zend_execute_data *ptr; + zend_execute_data *ptr, *skip; int lineno; char *function_name; char *filename; @@ -1596,9 +1596,21 @@ ZEND_FUNCTION(debug_print_backtrace) class_name = call_type = NULL; arg_array = NULL; - if (ptr->op_array) { - filename = ptr->op_array->filename; - lineno = ptr->opline->lineno; + + skip = ptr; + /* skip internal handler */ + if (!skip->op_array && + skip->prev_execute_data && + skip->prev_execute_data->opline && + skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL && + skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME && + skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) { + skip = skip->prev_execute_data; + } + + if (skip->op_array) { + filename = skip->op_array->filename; + lineno = skip->opline->lineno; } else { filename = NULL; lineno = 0; @@ -1678,7 +1690,7 @@ ZEND_FUNCTION(debug_print_backtrace) } zend_printf(") called at [%s:%d]\n", filename, lineno); include_filename = filename; - ptr = ptr->prev_execute_data; + ptr = skip->prev_execute_data; ++indent; if (free_class_name) { efree(free_class_name); @@ -1690,7 +1702,7 @@ ZEND_FUNCTION(debug_print_backtrace) ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last TSRMLS_DC) { - zend_execute_data *ptr; + zend_execute_data *ptr, *skip; int lineno; char *function_name; char *filename; @@ -1717,6 +1729,11 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last TSRML ptr = EG(current_execute_data); + /* skip "new Exception()" */ + if ((skip_last == 0) && ptr->opline && (ptr->opline->opcode == ZEND_NEW)) { + ptr = ptr->prev_execute_data; + } + /* skip debug_backtrace() */ if (skip_last--) { int arg_count = *((ulong*)(cur_arg_pos - 2)); @@ -1731,9 +1748,20 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last TSRML MAKE_STD_ZVAL(stack_frame); array_init(stack_frame); - if (ptr->op_array) { - filename = ptr->op_array->filename; - lineno = ptr->opline->lineno; + skip = ptr; + /* skip internal handler */ + if (!skip->op_array && + skip->prev_execute_data && + skip->prev_execute_data->opline && + skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL && + skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME && + skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) { + skip = skip->prev_execute_data; + } + + if (skip->op_array) { + filename = skip->op_array->filename; + lineno = skip->opline->lineno; add_assoc_string_ex(stack_frame, "file", sizeof("file"), filename, 1); add_assoc_long_ex(stack_frame, "line", sizeof("line"), lineno); @@ -1824,7 +1852,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last TSRML include_filename = filename; - ptr = ptr->prev_execute_data; + ptr = skip->prev_execute_data; } } /* }}} */ diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index bf6d718f18..560a6c6e01 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -596,6 +596,8 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS /* Initialize execute_data */ if (EG(current_execute_data)) { execute_data = *EG(current_execute_data); + EX(op_array) = NULL; + EX(opline) = NULL; } else { /* This only happens when we're called outside any execute()'s * It shouldn't be strictly necessary to NULL execute_data out,