Skip to content

Commit f37fe68

Browse files
committed
Fix closure GC handler for fake closures
Fixes oss-fuzz #31135.
1 parent 5959066 commit f37fe68

File tree

2 files changed

+30
-2
lines changed

2 files changed

+30
-2
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
Closure::fromCallabl() and GC
3+
--FILE--
4+
<?php
5+
6+
class Test {
7+
public function method() {}
8+
9+
public function method2($y) {
10+
static $x;
11+
$x = $y;
12+
}
13+
}
14+
15+
$fn = Closure::fromCallable([new Test, 'method2']);
16+
$fn($fn);
17+
unset($fn); // Still referenced from static var.
18+
gc_collect_cycles();
19+
20+
$fn = Closure::fromCallable([new Test, 'method']);
21+
$fn2 = $fn; unset($fn2); // Add to root buffer.
22+
gc_collect_cycles();
23+
24+
?>
25+
===DONE===
26+
--EXPECT--
27+
===DONE===

Zend/zend_closures.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -620,8 +620,9 @@ static HashTable *zend_closure_get_gc(zend_object *obj, zval **table, int *n) /*
620620

621621
*table = Z_TYPE(closure->this_ptr) != IS_NULL ? &closure->this_ptr : NULL;
622622
*n = Z_TYPE(closure->this_ptr) != IS_NULL ? 1 : 0;
623-
return (closure->func.type == ZEND_USER_FUNCTION &&
624-
closure->func.op_array.static_variables) ?
623+
/* Fake closures don't own the static variables they reference. */
624+
return (closure->func.type == ZEND_USER_FUNCTION
625+
&& !(closure->func.op_array.fn_flags & ZEND_ACC_FAKE_CLOSURE)) ?
625626
ZEND_MAP_PTR_GET(closure->func.op_array.static_variables_ptr) : NULL;
626627
}
627628
/* }}} */

0 commit comments

Comments
 (0)