Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 706bcdb

Browse files
Fix printing backtrace of fake generator frame
Fixes GH-15851 Closes GH-15952
1 parent c4c45da commit 706bcdb

File tree

4 files changed

+40
-0
lines changed

4 files changed

+40
-0
lines changed

‎NEWS‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ PHP NEWS
88
. Fixed bug GH-15905 (Assertion failure for TRACK_VARS_SERVER). (cmb)
99
. Fixed bug GH-15907 (Failed assertion when promoting Serialize deprecation to
1010
exception). (ilutov)
11+
. Fixed bug GH-15851 (Segfault when printing backtrace during cleanup of
12+
nested generator frame). (ilutov)
1113

1214
- Date:
1315
. Fixed bug GH-15582: Crash when not calling parent constructor of

‎Zend/tests/generators/gh15851.phpt‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
GH-15851: Access on NULL when printing backtrace with freed generator
3+
--FILE--
4+
<?php
5+
6+
class Foo {
7+
public function __destruct() {
8+
debug_print_backtrace();
9+
}
10+
}
11+
12+
function bar() {
13+
yield from foo();
14+
}
15+
16+
function foo() {
17+
$foo = new Foo();
18+
yield;
19+
}
20+
21+
$gen = bar();
22+
foreach ($gen as $dummy);
23+
24+
?>
25+
--EXPECTF--
26+
#0 %s(%d): Foo->__destruct()
27+
#1 %s(%d): bar()

‎Zend/zend_builtin_functions.c‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1725,6 +1725,16 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
17251725
}
17261726

17271727
while (call && (limit == 0 || frameno < limit)) {
1728+
if (UNEXPECTED(!call->func)) {
1729+
/* This is the fake frame inserted for nested generators. Normally,
1730+
* this frame is preceded by the actual generator frame and then
1731+
* replaced by zend_generator_check_placeholder_frame() below.
1732+
* However, the frame is popped before cleaning the stack frame,
1733+
* which is observable by destructors. */
1734+
call = zend_generator_check_placeholder_frame(call);
1735+
ZEND_ASSERT(call->func);
1736+
}
1737+
17281738
zend_execute_data *prev = call->prev_execute_data;
17291739

17301740
if (!prev) {

‎sapi/cli/php_cli.c‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,6 +1075,7 @@ static int do_cli(int argc, char **argv) /* {{{ */
10751075
object_init_ex(&ref, pce);
10761076

10771077
memset(&execute_data, 0, sizeof(zend_execute_data));
1078+
execute_data.func = (zend_function *) &zend_pass_function;
10781079
EG(current_execute_data) = &execute_data;
10791080
zend_call_known_instance_method_with_1_params(
10801081
pce->constructor, Z_OBJ(ref), NULL, &arg);

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /