Merge branch 'PHP-8.4'

* PHP-8.4:
  Prevent throwing in running generator
This commit is contained in:
Arnaud Le Blanc 2025-07-31 14:29:12 +02:00
commit 659f55a617
No known key found for this signature in database
3 changed files with 50 additions and 2 deletions

2
NEWS
View file

@ -13,6 +13,8 @@ PHP NEWS
(Arnaud)
. Fixed bug GH-19306 (Generator can be resumed while fetching next value from
delegated Generator). (Arnaud)
. Fixed bug GH-19326 (Calling Generator::throw() on a running generator with
a non-Generator delegate crashes). (Arnaud)
- Curl:
. Add support for CURLINFO_CONN_ID in curl_getinfo() (thecaliskan)

36
Zend/tests/gh19326.phpt Normal file
View file

@ -0,0 +1,36 @@
--TEST--
GH-19326: Calling Generator::throw() on a running generator with a non-Generator delegate crashes
--FILE--
<?php
class It implements IteratorAggregate {
public function getIterator(): Generator {
yield "";
Fiber::suspend();
}
}
function g() {
yield from new It();
}
$b = g();
$b->rewind();
$fiber = new Fiber(function () use ($b) {
$b->next();
});
$fiber->start();
try {
$b->throw(new Exception('test'));
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
$fiber->resume();
?>
--EXPECT--
Cannot resume an already running generator

View file

@ -498,8 +498,14 @@ ZEND_API zend_execute_data *zend_generator_check_placeholder_frame(zend_execute_
return ptr;
}
static void zend_generator_throw_exception(zend_generator *generator, zval *exception)
static zend_result zend_generator_throw_exception(zend_generator *generator, zval *exception)
{
if (generator->flags & ZEND_GENERATOR_CURRENTLY_RUNNING) {
zval_ptr_dtor(exception);
zend_throw_error(NULL, "Cannot resume an already running generator");
return FAILURE;
}
zend_execute_data *original_execute_data = EG(current_execute_data);
/* Throw the exception in the context of the generator. Decrementing the opline
@ -520,6 +526,8 @@ static void zend_generator_throw_exception(zend_generator *generator, zval *exce
}
EG(current_execute_data) = original_execute_data;
return SUCCESS;
}
static void zend_generator_add_child(zend_generator *generator, zend_generator *child)
@ -1026,7 +1034,9 @@ ZEND_METHOD(Generator, throw)
if (generator->execute_data) {
zend_generator *root = zend_generator_get_current(generator);
zend_generator_throw_exception(root, exception);
if (zend_generator_throw_exception(root, exception) == FAILURE) {
return;
}
zend_generator_resume(generator);