Skip to content

Commit 559ede1

Browse files
committed
Fixed bug #71013 (Incorrect exception handler with yield from)
1 parent 1d57440 commit 559ede1

File tree

3 files changed

+62
-3
lines changed

3 files changed

+62
-3
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ PHP NEWS
2626
from an array. (Bob)
2727
. Fixed bug #70987 (static::class within Closure::call() causes segfault).
2828
(Andrea)
29+
. Fixed bug #71013 (Incorrect exception handler with yield from). (Bob)
2930

3031
- CLI server:
3132
. Fixed bug #71005 (Segfault in php_cli_server_dispatch_router()). (Adam)

Zend/tests/generators/bug71013.phpt

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
--TEST--
2+
Bug #71013 (Incorrect exception handler with yield from)
3+
--FILE--
4+
<?php
5+
6+
class FooBar implements Iterator {
7+
function __construct() { echo "Constructing new FooBar\n"; }
8+
function __destruct() { echo "Destructing FooBar\n"; }
9+
function current () { throw new Exception; }
10+
function key () { return 0; }
11+
function next () {}
12+
function rewind () {}
13+
function valid () { return true; }
14+
}
15+
16+
function foo() {
17+
try {
18+
$f = new FooBar;
19+
yield from $f;
20+
} catch (Exception $e) {
21+
echo "[foo()] Caught Exception\n";
22+
}
23+
}
24+
25+
function bar() {
26+
echo "Starting bar()\n";
27+
$x = foo();
28+
try {
29+
var_dump($x->current());
30+
} catch (Exception $e) {
31+
echo "[bar()] Caught Exception\n";
32+
}
33+
echo "Unsetting \$x\n";
34+
unset($x);
35+
echo "Finishing bar()\n";
36+
}
37+
38+
bar();
39+
40+
?>
41+
--EXPECT--
42+
Starting bar()
43+
Constructing new FooBar
44+
[foo()] Caught Exception
45+
Destructing FooBar
46+
NULL
47+
Unsetting $x
48+
Finishing bar()
49+

Zend/zend_generators.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ static int zend_generator_get_next_delegated_value(zend_generator *generator) /*
573573
if (iter->index++ > 0) {
574574
iter->funcs->move_forward(iter);
575575
if (UNEXPECTED(EG(exception) != NULL)) {
576-
goto failure;
576+
goto exception;
577577
}
578578
}
579579

@@ -583,7 +583,9 @@ static int zend_generator_get_next_delegated_value(zend_generator *generator) /*
583583
}
584584

585585
value = iter->funcs->get_current_data(iter);
586-
if (UNEXPECTED(EG(exception) != NULL || !value)) {
586+
if (UNEXPECTED(EG(exception) != NULL)) {
587+
goto exception;
588+
} else if (UNEXPECTED(!value)) {
587589
goto failure;
588590
}
589591

@@ -595,14 +597,21 @@ static int zend_generator_get_next_delegated_value(zend_generator *generator) /*
595597
iter->funcs->get_current_key(iter, &generator->key);
596598
if (UNEXPECTED(EG(exception) != NULL)) {
597599
ZVAL_UNDEF(&generator->key);
598-
goto failure;
600+
goto exception;
599601
}
600602
} else {
601603
ZVAL_LONG(&generator->key, iter->index);
602604
}
603605
}
604606
return SUCCESS;
605607

608+
exception: {
609+
zend_execute_data *ex = EG(current_execute_data);
610+
EG(current_execute_data) = generator->execute_data;
611+
zend_throw_exception_internal(NULL);
612+
EG(current_execute_data) = ex;
613+
}
614+
606615
failure:
607616
zval_ptr_dtor(&generator->values);
608617
ZVAL_UNDEF(&generator->values);

0 commit comments

Comments
 (0)