From 5a1d8247f3531c98650915261cd89efde6afc472 Mon Sep 17 00:00:00 2001 From: lazerg Date: Sat, 8 Aug 2026 09:31:30 +0500 Subject: [PATCH] Fix GH-23113: stack overflow in array_replace_recursive() with deep arrays --- NEWS | 4 ++++ ext/standard/array.c | 7 +++++++ ext/standard/tests/array/gh23113.phpt | 27 +++++++++++++++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 ext/standard/tests/array/gh23113.phpt diff --git a/NEWS b/NEWS index ba832ef05888..5ad70b8be2c3 100644 --- a/NEWS +++ b/NEWS @@ -52,6 +52,10 @@ PHP NEWS - SQLite: . Fix leak when trying to close db if blob stream is still open. (ndossche) +- Standard: + . Fixed bug GH-23113 (Stack overflow in array_replace_recursive() with deeply + nested arrays). (Lazizbek Ergashev) + - Streams: . Fixed bug GH-15836 (Use-after-free when a user stream filter accesses $this->stream during the close flush). (iliaal) diff --git a/ext/standard/array.c b/ext/standard/array.c index 4527d9a80df8..838049e51bb2 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -4161,6 +4161,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/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-- + +--INI-- +zend.max_allowed_stack_size=256K +--FILE-- + $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?