Skip to content

Commit 8c556b2

Browse files
committed
Merge branch 'PHP-8.2' into PHP-8.3
* PHP-8.2: Fix printing backtrace of fake generator frame
2 parents 0226e5d + 706bcdb commit 8c556b2

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
- DOM:
1315
. Fixed bug GH-16039 (Segmentation fault (access null pointer) in

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
@@ -1766,6 +1766,16 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
17661766
}
17671767

17681768
while (call && (limit == 0 || frameno < limit)) {
1769+
if (UNEXPECTED(!call->func)) {
1770+
/* This is the fake frame inserted for nested generators. Normally,
1771+
* this frame is preceded by the actual generator frame and then
1772+
* replaced by zend_generator_check_placeholder_frame() below.
1773+
* However, the frame is popped before cleaning the stack frame,
1774+
* which is observable by destructors. */
1775+
call = zend_generator_check_placeholder_frame(call);
1776+
ZEND_ASSERT(call->func);
1777+
}
1778+
17691779
zend_execute_data *prev = call->prev_execute_data;
17701780

17711781
if (!prev) {

sapi/cli/php_cli.c

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

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

0 commit comments

Comments
 (0)