Skip to content

Commit 6ff0dcc

Browse files
committed
Merge branch 'PHP-8.5'
* PHP-8.5: Add a stack limit check in php_array_replace_recursive (#23124) Add a stack limit check in php_array_walk() (#23125)
2 parents 1d2ea5c + 5ae3f54 commit 6ff0dcc

3 files changed

Lines changed: 68 additions & 0 deletions

File tree

ext/standard/array.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,6 +1385,13 @@ static zend_result php_array_walk(
13851385
* levels of recursion. */
13861386
zend_fcall_info fci = context->fci;
13871387

1388+
#ifdef ZEND_CHECK_STACK_LIMIT
1389+
if (UNEXPECTED(zend_call_stack_overflowed(EG(stack_limit)))) {
1390+
zend_call_stack_size_error();
1391+
return FAILURE;
1392+
}
1393+
#endif
1394+
13881395
if (zend_hash_num_elements(target_hash) == 0) {
13891396
return result;
13901397
}
@@ -4048,6 +4055,13 @@ PHPAPI int php_array_replace_recursive(HashTable *dest, HashTable *src) /* {{{ *
40484055
zend_ulong num_key;
40494056
int ret;
40504057

4058+
#ifdef ZEND_CHECK_STACK_LIMIT
4059+
if (UNEXPECTED(zend_call_stack_overflowed(EG(stack_limit)))) {
4060+
zend_call_stack_size_error();
4061+
return 0;
4062+
}
4063+
#endif
4064+
40514065
ZEND_HASH_FOREACH_KEY_VAL(src, num_key, string_key, src_entry) {
40524066
src_zval = src_entry;
40534067
ZVAL_DEREF(src_zval);
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
GH-23111 (Stack overflow in array_walk_recursive with deeply nested arrays)
3+
--SKIPIF--
4+
<?php
5+
if (ini_get('zend.max_allowed_stack_size') === false) {
6+
die('skip No stack limit support');
7+
}
8+
if (getenv('SKIP_ASAN')) {
9+
die('skip ASAN needs different stack limit setting due to more stack space usage');
10+
}
11+
?>
12+
--INI--
13+
zend.max_allowed_stack_size=256K
14+
--FILE--
15+
<?php
16+
$a = [];
17+
for ($i = 0; $i < 30000; $i++) {
18+
$a = [$a];
19+
}
20+
try {
21+
array_walk_recursive($a, function ($v) {});
22+
} catch (Throwable $e) {
23+
echo $e::class, ": ", $e->getMessage(), "\n";
24+
}
25+
?>
26+
--EXPECTF--
27+
Error: Maximum call stack size of %d bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion?
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
GH-23113 (Stack overflow in array_replace_recursive with deeply nested arrays)
3+
--SKIPIF--
4+
<?php
5+
if (ini_get('zend.max_allowed_stack_size') === false) {
6+
die('skip No stack limit support');
7+
}
8+
if (getenv('SKIP_ASAN')) {
9+
die('skip ASAN needs different stack limit setting due to more stack space usage');
10+
}
11+
?>
12+
--INI--
13+
zend.max_allowed_stack_size=256K
14+
--FILE--
15+
<?php
16+
$a = [];
17+
for ($i = 0; $i < 30000; $i++) {
18+
$a = ['k' => $a];
19+
}
20+
try {
21+
array_replace_recursive($a, $a);
22+
} catch (Throwable $e) {
23+
echo $e::class, ": ", $e->getMessage(), "\n";
24+
}
25+
?>
26+
--EXPECTF--
27+
Error: Maximum call stack size of %d bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion?

0 commit comments

Comments
 (0)