Merge branch 'PHP-8.4'

* PHP-8.4:
  Fix printing backtrace of fake generator frame
This commit is contained in:
Ilija Tovilo 2024-09-27 17:37:14 +02:00
commit a58df54bc4
No known key found for this signature in database
GPG Key ID: 5050C66BFCD1015A
3 changed files with 38 additions and 0 deletions

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

@ -1883,6 +1883,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

@ -1045,6 +1045,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);