Merge branch 'PHP-8.2'

* PHP-8.2:
  Fix a memory leak in tracig JIT when the same closure is called through Closure::call() and natively.
This commit is contained in:
Dmitry Stogov 2022-11-22 12:29:36 +03:00
commit ff85649431
2 changed files with 56 additions and 6 deletions

View file

@ -160,15 +160,21 @@ ZEND_METHOD(Closure, call)
/* copied upon generator creation */ /* copied upon generator creation */
GC_DELREF(&closure->std); GC_DELREF(&closure->std);
} else { } else {
zend_closure *fake_closure;
zend_function *my_function; zend_function *my_function;
fake_closure = emalloc(sizeof(zend_closure));
memset(&fake_closure->std, 0, sizeof(fake_closure->std));
fake_closure->std.gc.refcount = 1;
fake_closure->std.gc.u.type_info = GC_NULL;
ZVAL_UNDEF(&fake_closure->this_ptr);
fake_closure->called_scope = NULL;
my_function = &fake_closure->func;
if (ZEND_USER_CODE(closure->func.type)) { if (ZEND_USER_CODE(closure->func.type)) {
my_function = emalloc(sizeof(zend_op_array));
memcpy(my_function, &closure->func, sizeof(zend_op_array)); memcpy(my_function, &closure->func, sizeof(zend_op_array));
} else { } else {
my_function = emalloc(sizeof(zend_internal_function));
memcpy(my_function, &closure->func, sizeof(zend_internal_function)); memcpy(my_function, &closure->func, sizeof(zend_internal_function));
} }
my_function->common.fn_flags &= ~ZEND_ACC_CLOSURE;
/* use scope of passed object */ /* use scope of passed object */
my_function->common.scope = newclass; my_function->common.scope = newclass;
if (closure->func.type == ZEND_INTERNAL_FUNCTION) { if (closure->func.type == ZEND_INTERNAL_FUNCTION) {
@ -194,10 +200,8 @@ ZEND_METHOD(Closure, call)
if (fci_cache.function_handler->common.fn_flags & ZEND_ACC_HEAP_RT_CACHE) { if (fci_cache.function_handler->common.fn_flags & ZEND_ACC_HEAP_RT_CACHE) {
efree(ZEND_MAP_PTR(my_function->op_array.run_time_cache)); efree(ZEND_MAP_PTR(my_function->op_array.run_time_cache));
} }
efree_size(my_function, sizeof(zend_op_array));
} else {
efree_size(my_function, sizeof(zend_internal_function));
} }
efree_size(fake_closure, sizeof(zend_closure));
} }
if (Z_TYPE(closure_result) != IS_UNDEF) { if (Z_TYPE(closure_result) != IS_UNDEF) {

View file

@ -0,0 +1,46 @@
--TEST--
Closures should be always called with ZEND_ACC_CLOSURE flag set
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.file_update_protection=0
opcache.jit_buffer_size=1M
opcache.protect_memory=1
opcache.jit_hot_func=2
--EXTENSIONS--
opcache
--FILE--
<?php
class Foo {
}
function bar() {
return function () {
return function () {
return function () {
return 42;
};
};
};
}
$foo = new Foo;
$f = bar();
var_dump($f->call($foo));
var_dump($f->call($foo));
var_dump($f());
?>
--EXPECT--
object(Closure)#3 (1) {
["this"]=>
object(Foo)#1 (0) {
}
}
object(Closure)#3 (1) {
["this"]=>
object(Foo)#1 (0) {
}
}
object(Closure)#3 (0) {
}