Merge branch 'PHP-8.2' into PHP-8.3

* PHP-8.2:
  Fix printing backtrace of fake generator frame
This commit is contained in:
Ilija Tovilo 2024-09-27 17:35:55 +02:00
commit 8c556b211d
No known key found for this signature in database
GPG key ID: 5050C66BFCD1015A
4 changed files with 40 additions and 0 deletions

2
NEWS
View file

@ -8,6 +8,8 @@ PHP NEWS
. Fixed bug GH-15905 (Assertion failure for TRACK_VARS_SERVER). (cmb)
. Fixed bug GH-15907 (Failed assertion when promoting Serialize deprecation to
exception). (ilutov)
. Fixed bug GH-15851 (Segfault when printing backtrace during cleanup of
nested generator frame). (ilutov)
- DOM:
. Fixed bug GH-16039 (Segmentation fault (access null pointer) in

View file

@ -0,0 +1,27 @@
--TEST--
GH-15851: Access on NULL when printing backtrace with freed generator
--FILE--
<?php
class Foo {
public function __destruct() {
debug_print_backtrace();
}
}
function bar() {
yield from foo();
}
function foo() {
$foo = new Foo();
yield;
}
$gen = bar();
foreach ($gen as $dummy);
?>
--EXPECTF--
#0 %s(%d): Foo->__destruct()
#1 %s(%d): bar()

View file

@ -1766,6 +1766,16 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
}
while (call && (limit == 0 || frameno < limit)) {
if (UNEXPECTED(!call->func)) {
/* This is the fake frame inserted for nested generators. Normally,
* this frame is preceded by the actual generator frame and then
* replaced by zend_generator_check_placeholder_frame() below.
* However, the frame is popped before cleaning the stack frame,
* which is observable by destructors. */
call = zend_generator_check_placeholder_frame(call);
ZEND_ASSERT(call->func);
}
zend_execute_data *prev = call->prev_execute_data;
if (!prev) {

View file

@ -1076,6 +1076,7 @@ do_repeat:
object_init_ex(&ref, pce);
memset(&execute_data, 0, sizeof(zend_execute_data));
execute_data.func = (zend_function *) &zend_pass_function;
EG(current_execute_data) = &execute_data;
zend_call_known_instance_method_with_1_params(
pce->constructor, Z_OBJ(ref), NULL, &arg);