Skip to content

Commit 4411026

Browse files
committed
Close generator already in dtor phase
In the added test case, the Closure ends up being freed before the generator during GC. This patch closes the generator (and thus releases the held closure / execute_data) already during dtor_obj, which will avoid ordering issues in free_obj. dtor_obj is not always called, but if it isn't, then we also won't run GC and will free_obj in reverse construction order. Fixes oss-fuzz #33947.
1 parent 2aac616 commit 4411026

File tree

2 files changed

+21
-1
lines changed

2 files changed

+21
-1
lines changed

Zend/tests/generators/gc_order.phpt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
Close generator in dtor to avoid freeing order issues
3+
--FILE--
4+
<?php
5+
6+
$gen = function() {
7+
yield;
8+
throw new Exception; // Just to create a live range
9+
};
10+
$a = new stdclass;
11+
$a->a = $a;
12+
$a->gen = $gen();
13+
14+
?>
15+
===DONE===
16+
--EXPECT--
17+
===DONE===

Zend/zend_generators.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */
226226

227227
if (EXPECTED(!ex) || EXPECTED(!(ex->func->op_array.fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK))
228228
|| CG(unclean_shutdown)) {
229+
zend_generator_close(generator, 0);
229230
return;
230231
}
231232

@@ -265,7 +266,7 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */
265266

266267
/* TODO: If we hit another yield inside try/finally,
267268
* should we also jump to the next finally block? */
268-
return;
269+
break;
269270
} else if (op_num < try_catch->finally_end) {
270271
zval *fast_call =
271272
ZEND_CALL_VAR(ex, ex->func->op_array.opcodes[try_catch->finally_end].op1.var);
@@ -284,6 +285,8 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */
284285

285286
try_catch_offset--;
286287
}
288+
289+
zend_generator_close(generator, 0);
287290
}
288291
/* }}} */
289292

0 commit comments

Comments
 (0)