Fix closure GC handler for fake closures

Fixes oss-fuzz #31135.
This commit is contained in:
Nikita Popov 2021-02-20 11:16:37 +01:00
parent 59590663d7
commit f37fe68e63
2 changed files with 30 additions and 2 deletions

View File

@ -0,0 +1,27 @@
--TEST--
Closure::fromCallabl() and GC
--FILE--
<?php
class Test {
public function method() {}
public function method2($y) {
static $x;
$x = $y;
}
}
$fn = Closure::fromCallable([new Test, 'method2']);
$fn($fn);
unset($fn); // Still referenced from static var.
gc_collect_cycles();
$fn = Closure::fromCallable([new Test, 'method']);
$fn2 = $fn; unset($fn2); // Add to root buffer.
gc_collect_cycles();
?>
===DONE===
--EXPECT--
===DONE===

View File

@ -620,8 +620,9 @@ static HashTable *zend_closure_get_gc(zend_object *obj, zval **table, int *n) /*
*table = Z_TYPE(closure->this_ptr) != IS_NULL ? &closure->this_ptr : NULL;
*n = Z_TYPE(closure->this_ptr) != IS_NULL ? 1 : 0;
return (closure->func.type == ZEND_USER_FUNCTION &&
closure->func.op_array.static_variables) ?
/* Fake closures don't own the static variables they reference. */
return (closure->func.type == ZEND_USER_FUNCTION
&& !(closure->func.op_array.fn_flags & ZEND_ACC_FAKE_CLOSURE)) ?
ZEND_MAP_PTR_GET(closure->func.op_array.static_variables_ptr) : NULL;
}
/* }}} */