mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Merge branch 'PHP-8.2' into PHP-8.3
* PHP-8.2: Fix freeing of incompletely initialized closures
This commit is contained in:
commit
baf74ed1a4
3 changed files with 37 additions and 7 deletions
2
NEWS
2
NEWS
|
@ -6,6 +6,8 @@ PHP NEWS
|
|||
. Fixed GH-11847 (DTrace enabled build is broken). (Filip Zrůst)
|
||||
. Fixed bug GH-11876: ini_parse_quantity() accepts invalid quantities.
|
||||
(Girgias)
|
||||
. Fixed bug GH-12073 (Segfault when freeing incompletely initialized
|
||||
closures). (ilutov)
|
||||
|
||||
- FPM:
|
||||
. Fixed GH-12077 (PHP 8.3.0RC1 borked socket-close-on-exec.phpt).
|
||||
|
|
28
Zend/tests/gh12073.phpt
Normal file
28
Zend/tests/gh12073.phpt
Normal file
|
@ -0,0 +1,28 @@
|
|||
--TEST--
|
||||
GH-12073: Freeing of non-ZMM pointer of incompletely allocated closure
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (getenv("USE_ZEND_ALLOC") === "0" && getenv("USE_TRACKED_ALLOC") !== "1") {
|
||||
die("skip Zend MM disabled");
|
||||
}
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test() {
|
||||
$k = 1;
|
||||
return function () use ($k) {
|
||||
foo();
|
||||
};
|
||||
}
|
||||
|
||||
ini_set('memory_limit', '2M');
|
||||
|
||||
$array = [];
|
||||
for ($i = 0; $i < 10_000; $i++) {
|
||||
$array[] = test();
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d
|
|
@ -732,6 +732,11 @@ static void zend_create_closure_ex(zval *res, zend_function *func, zend_class_en
|
|||
closure->func.common.fn_flags |= ZEND_ACC_CLOSURE;
|
||||
closure->func.common.fn_flags &= ~ZEND_ACC_IMMUTABLE;
|
||||
|
||||
zend_string_addref(closure->func.op_array.function_name);
|
||||
if (closure->func.op_array.refcount) {
|
||||
(*closure->func.op_array.refcount)++;
|
||||
}
|
||||
|
||||
/* For fake closures, we want to reuse the static variables of the original function. */
|
||||
if (!is_fake) {
|
||||
if (closure->func.op_array.static_variables) {
|
||||
|
@ -765,22 +770,17 @@ static void zend_create_closure_ex(zval *res, zend_function *func, zend_class_en
|
|||
if (func->common.scope != scope) {
|
||||
func->common.scope = scope;
|
||||
}
|
||||
closure->func.op_array.fn_flags &= ~ZEND_ACC_HEAP_RT_CACHE;
|
||||
ptr = zend_arena_alloc(&CG(arena), func->op_array.cache_size);
|
||||
ZEND_MAP_PTR_SET(func->op_array.run_time_cache, ptr);
|
||||
closure->func.op_array.fn_flags &= ~ZEND_ACC_HEAP_RT_CACHE;
|
||||
} else {
|
||||
/* Otherwise, we use a non-shared runtime cache */
|
||||
closure->func.op_array.fn_flags |= ZEND_ACC_HEAP_RT_CACHE;
|
||||
ptr = emalloc(func->op_array.cache_size);
|
||||
closure->func.op_array.fn_flags |= ZEND_ACC_HEAP_RT_CACHE;
|
||||
}
|
||||
memset(ptr, 0, func->op_array.cache_size);
|
||||
}
|
||||
ZEND_MAP_PTR_INIT(closure->func.op_array.run_time_cache, ptr);
|
||||
|
||||
zend_string_addref(closure->func.op_array.function_name);
|
||||
if (closure->func.op_array.refcount) {
|
||||
(*closure->func.op_array.refcount)++;
|
||||
}
|
||||
} else {
|
||||
memcpy(&closure->func, func, sizeof(zend_internal_function));
|
||||
closure->func.common.fn_flags |= ZEND_ACC_CLOSURE;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue