]> granicus.if.org Git - php/commitdiff
Fixed bug #29896 (Backtrace argument list out of sync)
authorDmitry Stogov <dmitry@php.net>
Wed, 22 Jun 2005 15:24:15 +0000 (15:24 +0000)
committerDmitry Stogov <dmitry@php.net>
Wed, 22 Jun 2005 15:24:15 +0000 (15:24 +0000)
NEWS
Zend/tests/bug29896.phpt [new file with mode: 0755]
Zend/zend_builtin_functions.c
Zend/zend_execute_API.c

diff --git a/NEWS b/NEWS
index 9b8d9f527e358dba916456fad03f6e3c2901d6e6..d5c69d170640441d5984326964e528222fa4590f 100644 (file)
--- 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 (executable)
index 0000000..1e2eb0b
--- /dev/null
@@ -0,0 +1,28 @@
+--TEST--
+Bug #29896 (Backtrace argument list out of sync)
+--FILE--
+<?php
+function userErrorHandler($num, $msg, $file, $line, $vars)
+{
+    debug_print_backtrace();
+}
+
+$OldErrorHandler = set_error_handler("userErrorHandler");
+
+function GenerateError1($A1)
+{
+    $a = $b;
+}
+
+function GenerateError2($A1)
+{
+    GenerateError1("Test1");
+}
+
+GenerateError2("Test2");
+?>
+--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]
+
index 7db7816ce32d9579a3bcd9cfd3e71e104b15f5e2..d5324da41ac0886b197b7f895bde4392b58d1119 100644 (file)
@@ -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;
        }
 }
 /* }}} */
index bf6d718f18f6715bef9edd3856b6e0fd19ec250c..560a6c6e01016d3487b2eae2b8f44a4346eba23c 100644 (file)
@@ -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,