Skip to content

Commit 02dca18

Browse files
committed
Fix bug #65764
I'm not exactly sure whether this is the right way to fix it. The question is whether Generator::throw() on a newborn generator (i.e. a generator that is not yet at yield expression) should first advance to the first yield and throw the exception there or whether it should instead throw the exception in the caller's context. The old behavior was to throw it at the start of the function (i.e. the very first opcode), which causes issues like the one in #65764. Effectively it's impossible to properly handle the exceptions in this case. For now I choose the variant where the generator advances to the first yield before throwing, as that's consistent with how all other methods on the Generator object currently behave. This does not necessarily match the behavior in other languages, e.g. Python would throw the exception in the caller's context. But then our send() method already has this kind of deviation, so it stays internally consistent at least.
1 parent af60886 commit 02dca18

File tree

4 files changed

+9
-1
lines changed

4 files changed

+9
-1
lines changed

NEWS

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ PHP NEWS
44

55
- Core:
66
. Added validation of class names in the autoload process. (Dmitry)
7-
. Fixed buf #66041 (list() fails to unpack yielded ArrayAccess object).
7+
. Fixed bug #66041 (list() fails to unpack yielded ArrayAccess object).
88
(Nikita)
9+
. Fixed bug #65764 (generators/throw_rethrow FAIL with
10+
ZEND_COMPILE_EXTENDED_INFO). (Nikita)
911

1012
- Date:
1113
. Fixed bug #66060 (Heap buffer over-read in DateInterval). (Remi)

Zend/tests/generators/throw_caught.phpt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Generator::throw() where the exception is caught in the generator
44
<?php
55

66
function gen() {
7+
echo "before yield\n";
78
try {
89
yield;
910
} catch (RuntimeException $e) {
@@ -18,6 +19,7 @@ var_dump($gen->throw(new RuntimeException('Test')));
1819

1920
?>
2021
--EXPECTF--
22+
before yield
2123
exception 'RuntimeException' with message 'Test' in %s:%d
2224
Stack trace:
2325
#0 {main}

Zend/tests/generators/throw_rethrow.phpt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Generator::throw() where the generator throws a different exception
44
<?php
55

66
function gen() {
7+
echo "before yield\n";
78
try {
89
yield;
910
} catch (RuntimeException $e) {
@@ -18,6 +19,7 @@ var_dump($gen->throw(new RuntimeException('throw')));
1819

1920
?>
2021
--EXPECTF--
22+
before yield
2123
Caught: exception 'RuntimeException' with message 'throw' in %s:%d
2224
Stack trace:
2325
#0 {main}

Zend/zend_generators.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,8 @@ ZEND_METHOD(Generator, throw)
560560

561561
generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC);
562562

563+
zend_generator_ensure_initialized(generator TSRMLS_CC);
564+
563565
if (generator->execute_data) {
564566
/* Throw the exception in the context of the generator */
565567
zend_execute_data *current_execute_data = EG(current_execute_data);

0 commit comments

Comments
 (0)