[php-src] master: Merge branch 'PHP-8.5'
Arnaud Le Blanc <[email protected]>
| Newsgroups | gmane.comp.php.cvs.general |
|---|---|
| Message-ID | <[email protected]> |
Author: Arnaud Le Blanc (arnaud-lb)
Date: 2026-08-10T12:01:23+02:00
Commit: https://github.com/php/php-src/commit/6ff0dcc0664ac92f7616bdfeced76d89790e5928
Raw diff: https://github.com/php/php-src/commit/6ff0dcc0664ac92f7616bdfeced76d89790e5928.diff
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)
Changed paths:
A ext/standard/tests/array/gh23111.phpt
A ext/standard/tests/array/gh23113.phpt
M ext/standard/array.c
Diff:
diff --git a/ext/standard/array.c b/ext/standard/array.c
index 584afada2089..4dc12d0f59cc 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -1385,6 +1385,13 @@ static zend_result php_array_walk(
* levels of recursion. */
zend_fcall_info fci = context->fci;
+#ifdef ZEND_CHECK_STACK_LIMIT
+ if (UNEXPECTED(zend_call_stack_overflowed(EG(stack_limit)))) {
+ zend_call_stack_size_error();
+ return FAILURE;
+ }
+#endif
+
if (zend_hash_num_elements(target_hash) == 0) {
return result;
}
@@ -4048,6 +4055,13 @@ PHPAPI int php_array_replace_recursive(HashTable *dest, HashTable *src) /* {{{ *
zend_ulong num_key;
int ret;
+#ifdef ZEND_CHECK_STACK_LIMIT
+ if (UNEXPECTED(zend_call_stack_overflowed(EG(stack_limit)))) {
+ zend_call_stack_size_error();
+ return 0;
+ }
+#endif
+
ZEND_HASH_FOREACH_KEY_VAL(src, num_key, string_key, src_entry) {
src_zval = src_entry;
ZVAL_DEREF(src_zval);
diff --git a/ext/standard/tests/array/gh23111.phpt b/ext/standard/tests/array/gh23111.phpt
new file mode 100644
index 000000000000..21db33a2fc75
--- /dev/null
+++ b/ext/standard/tests/array/gh23111.phpt
@@ -0,0 +1,27 @@
+--TEST--
+GH-23111 (Stack overflow in array_walk_recursive with deeply nested arrays)
+--SKIPIF--
+<?php
+if (ini_get('zend.max_allowed_stack_size') === false) {
+ die('skip No stack limit support');
+}
+if (getenv('SKIP_ASAN')) {
+ die('skip ASAN needs different stack limit setting due to more stack space usage');
+}
+?>
+--INI--
+zend.max_allowed_stack_size=256K
+--FILE--
+<?php
+$a = [];
+for ($i = 0; $i < 30000; $i++) {
+ $a = [$a];
+}
+try {
+ array_walk_recursive($a, function ($v) {});
+} catch (Throwable $e) {
+ echo $e::class, ": ", $e->getMessage(), "\n";
+}
+?>
+--EXPECTF--
+Error: Maximum call stack size of %d bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion?
diff --git a/ext/standard/tests/array/gh23113.phpt b/ext/standard/tests/array/gh23113.phpt
new file mode 100644
index 000000000000..894e8d971e53
--- /dev/null
+++ b/ext/standard/tests/array/gh23113.phpt
@@ -0,0 +1,27 @@
+--TEST--
+GH-23113 (Stack overflow in array_replace_recursive with deeply nested arrays)
+--SKIPIF--
+<?php
+if (ini_get('zend.max_allowed_stack_size') === false) {
+ die('skip No stack limit support');
+}
+if (getenv('SKIP_ASAN')) {
+ die('skip ASAN needs different stack limit setting due to more stack space usage');
+}
+?>
+--INI--
+zend.max_allowed_stack_size=256K
+--FILE--
+<?php
+$a = [];
+for ($i = 0; $i < 30000; $i++) {
+ $a = ['k' => $a];
+}
+try {
+ array_replace_recursive($a, $a);
+} catch (Throwable $e) {
+ echo $e::class, ": ", $e->getMessage(), "\n";
+}
+?>
+--EXPECTF--
+Error: Maximum call stack size of %d bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion?