Skip to content

Commit

Permalink
Merge branch 'PHP-8.3'
Browse files Browse the repository at this point in the history
* PHP-8.3:
  Fix freeing of incompletely initialized closures
  • Loading branch information
iluuu1994 committed Sep 4, 2023
2 parents acd7769 + baf74ed commit 3f38105
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 7 deletions.
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,8 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? ????, PHP 8.4.0alpha1

Core:
. Fixed bug GH-12073 (Segfault when freeing incompletely initialized
closures). (ilutov)

<<< NOTE: Insert NEWS from last stable release here prior to actual release! >>>
28 changes: 28 additions & 0 deletions Zend/tests/gh12073.phpt
Original file line number Diff line number Diff line change
@@ -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
14 changes: 7 additions & 7 deletions Zend/zend_closures.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 3f38105

Please sign in to comment.