Skip to content

Commit 5a1d824

Browse files
committed
Fix GH-23113: stack overflow in array_replace_recursive() with deep arrays
1 parent 905afb5 commit 5a1d824

3 files changed

Lines changed: 38 additions & 0 deletions

File tree

‎NEWS‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ PHP NEWS
5252
- SQLite:
5353
. Fix leak when trying to close db if blob stream is still open. (ndossche)
5454

55+
- Standard:
56+
. Fixed bug GH-23113 (Stack overflow in array_replace_recursive() with deeply
57+
nested arrays). (Lazizbek Ergashev)
58+
5559
- Streams:
5660
. Fixed bug GH-15836 (Use-after-free when a user stream filter accesses
5761
$this->stream during the close flush). (iliaal)

‎ext/standard/array.c‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4161,6 +4161,13 @@ PHPAPI int php_array_replace_recursive(HashTable *dest, HashTable *src) /* {{{ *
41614161
zend_ulong num_key;
41624162
int ret;
41634163

4164+
#ifdef ZEND_CHECK_STACK_LIMIT
4165+
if (UNEXPECTED(zend_call_stack_overflowed(EG(stack_limit)))) {
4166+
zend_call_stack_size_error();
4167+
return 0;
4168+
}
4169+
#endif
4170+
41644171
ZEND_HASH_FOREACH_KEY_VAL(src, num_key, string_key, src_entry) {
41654172
src_zval = src_entry;
41664173
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-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)