Skip to content

Commit bad5d0d

Browse files
committed
Fixed bug #74954 (null deref and segfault in zend_generator_resume())
1 parent e405ff5 commit bad5d0d

File tree

3 files changed

+48
-4
lines changed

3 files changed

+48
-4
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ PHP NEWS
44

55
- Core:
66
. Fixed bug #74947 (Segfault in scanner on INF number). (Laruence)
7+
. Fixed bug #74954 (null deref and segfault in zend_generator_resume()). (Bob)
78

89
- SimpleXML:
910
. Fixed bug #74950 (nullpointer deref in simplexml_element_getDocNamespaces).

Zend/tests/generators/bug74954.phpt

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
--TEST--
2+
Bug #74954 (crash after update of generator yielding from finished generator)
3+
--FILE--
4+
<?php
5+
6+
function from() {
7+
yield 1;
8+
throw new Exception();
9+
}
10+
11+
function gen($gen) {
12+
try {
13+
var_dump(yield from $gen);
14+
} catch (Exception $e) { print "Caught exception!\n$e\n"; }
15+
}
16+
17+
$gen = from();
18+
$gens[] = gen($gen);
19+
$gens[] = gen($gen);
20+
21+
foreach ($gens as $g) {
22+
$g->current();
23+
}
24+
25+
do {
26+
foreach ($gens as $i => $g) {
27+
$g->next();
28+
}
29+
} while($gens[0]->valid());
30+
31+
?>
32+
--EXPECTF--
33+
Caught exception!
34+
Exception in %s:%d
35+
Stack trace:
36+
#0 %s(%d): from()
37+
#1 [internal function]: gen(Object(Generator))
38+
#2 %s(%d): Generator->next()
39+
#3 {main}
40+
Caught exception!
41+
ClosedGeneratorException: Generator yielded from aborted, no return value available in %s:%d
42+
Stack trace:
43+
#0 [internal function]: gen(Object(Generator))
44+
#1 %s(%d): Generator->next()
45+
#2 {main}

Zend/zend_generators.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -644,15 +644,13 @@ exception: {
644644

645645
ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */
646646
{
647-
zend_generator *generator;
647+
zend_generator *generator = zend_generator_get_current(orig_generator);
648648

649649
/* The generator is already closed, thus can't resume */
650-
if (UNEXPECTED(!orig_generator->execute_data)) {
650+
if (UNEXPECTED(!generator->execute_data)) {
651651
return;
652652
}
653653

654-
generator = zend_generator_get_current(orig_generator);
655-
656654
try_again:
657655
if (generator->flags & ZEND_GENERATOR_CURRENTLY_RUNNING) {
658656
zend_throw_error(NULL, "Cannot resume an already running generator");

0 commit comments

Comments
 (0)