]> 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:26:05 +0000 (15:26 +0000)
committerDmitry Stogov <dmitry@php.net>
Wed, 22 Jun 2005 15:26:05 +0000 (15:26 +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 edde30249ea82df9003c62f6f4d4276eee349c4d..95fd8eda4a359a57a3fe8796570a191ad2ee9aa0 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,7 @@ PHP                                                                        NEWS
 - Fixed bug #33427 (ext/odbc: check if unixODBC header file exists). (Jani)
 - Fixed bug #33257 (array_splice() inconsistent when passed function instead
   of variable). (Dmitry)
+- Fixed bug #29896 (Backtrace argument list out of sync). (Dmitry)
 - Fixed bug #15854 (boolean ini options may be incorrectly displayed as Off 
   when they are On). (Tony)
 
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 9fb2bfd68d7c4ccb59cf5d8089e70a32af3cbe98..df4e7bd3eefea06b0553c724364b0b72e28514f8 100644 (file)
@@ -1644,7 +1644,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;
@@ -1689,9 +1689,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;
@@ -1770,7 +1782,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);
@@ -1782,7 +1794,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;
@@ -1809,12 +1821,17 @@ 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() */
-       ptr = ptr->prev_execute_data;
        if (skip_last--) {
                int arg_count = *((ulong*)(cur_arg_pos - 2));
                cur_arg_pos -= (arg_count + 2);
                frames_on_stack--;
+               ptr = ptr->prev_execute_data;
        }
 
        array_init(return_value);
@@ -1823,9 +1840,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);
 
@@ -1916,7 +1944,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 8c527ec591c70624c36927a7116a27a86c5672a8..82e59f7651d2230b2204f56ac6204a3a5afcf554 100644 (file)
@@ -587,6 +587,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,