Skip to content

Commit 0eb0282

Browse files
committed
Fixed bug #38047 ("file" and "line" sometimes not set in backtrace from inside error handler)
1 parent 6d6bd77 commit 0eb0282

File tree

2 files changed

+81
-1
lines changed

2 files changed

+81
-1
lines changed

Zend/tests/bug38047.phpt

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
--TEST--
2+
Bug #38047 ("file" and "line" sometimes not set in backtrace from inside error handler)
3+
--FILE--
4+
<?php
5+
error_reporting(E_ALL);
6+
set_error_handler('kalus_error_handler');
7+
ini_set("display_errors", "on");
8+
9+
class A {
10+
function A_ftk($a) {
11+
}
12+
}
13+
14+
function kalus_error_handler($error_code, $error_string, $filename, $line, $symbols) {
15+
echo "$error_string\n";
16+
get_error_context();
17+
}
18+
19+
function get_error_context() {
20+
$backtrace = debug_backtrace();
21+
$n = 1;
22+
foreach ($backtrace as $call) {
23+
echo $n++." ";
24+
if (isset($call["file"])) {
25+
echo $call["file"];
26+
if (isset($call["line"])) {
27+
echo ":".$call["line"];
28+
}
29+
}
30+
if (isset($call["function"])) {
31+
echo " ".$call["function"]."()";
32+
}
33+
echo "\n";
34+
}
35+
echo "\n";
36+
}
37+
38+
//This will not create file and line items for the call into the error handler
39+
$page["name"] = A::A_ftk();
40+
?>
41+
--EXPECTF--
42+
Non-static method A::A_ftk() should not be called statically
43+
1 %sbug38047.php:13 get_error_context()
44+
2 %sbug38047.php:36 kalus_error_handler()
45+
3 %sbug38047.php:36 A_ftk()
46+
47+
Missing argument 1 for A::A_ftk(), called in %sbug38047.php on line 36 and defined
48+
1 %sbug38047.php:13 get_error_context()
49+
2 %sbug38047.php:7 kalus_error_handler()
50+
3 %sbug38047.php:36 A_ftk()

Zend/zend_builtin_functions.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1935,7 +1935,23 @@ ZEND_FUNCTION(debug_print_backtrace)
19351935
if (filename) {
19361936
zend_printf(") called at [%s:%d]\n", filename, lineno);
19371937
} else {
1938-
ZEND_PUTS(")\n");
1938+
zend_execute_data *prev = skip->prev_execute_data;
1939+
1940+
while (prev) {
1941+
if (prev->function_state.function &&
1942+
prev->function_state.function->common.type != ZEND_USER_FUNCTION) {
1943+
prev = NULL;
1944+
break;
1945+
}
1946+
if (prev->op_array) {
1947+
zend_printf(") called at [%s:%d]\n", prev->op_array->filename, prev->opline->lineno);
1948+
break;
1949+
}
1950+
prev = prev->prev_execute_data;
1951+
}
1952+
if (!prev) {
1953+
ZEND_PUTS(")\n");
1954+
}
19391955
}
19401956
include_filename = filename;
19411957
ptr = skip->prev_execute_data;
@@ -2029,6 +2045,20 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
20292045
* and debug_baktrace() might have been called by the error_handler. in this case we don't
20302046
* want to pop anything of the argument-stack */
20312047
} else {
2048+
zend_execute_data *prev = skip->prev_execute_data;
2049+
2050+
while (prev) {
2051+
if (prev->function_state.function &&
2052+
prev->function_state.function->common.type != ZEND_USER_FUNCTION) {
2053+
break;
2054+
}
2055+
if (prev->op_array) {
2056+
add_assoc_string_ex(stack_frame, "file", sizeof("file"), prev->op_array->filename, 1);
2057+
add_assoc_long_ex(stack_frame, "line", sizeof("line"), prev->opline->lineno);
2058+
break;
2059+
}
2060+
prev = prev->prev_execute_data;
2061+
}
20322062
filename = NULL;
20332063
}
20342064

0 commit comments

Comments
 (0)