[php-src] PHP-8.5: Merge branch 'PHP-8.4' into 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-10T10:09:32+02:00

Commit: https://github.com/php/php-src/commit/266c8d9975d01dbbe3a2d4429410b5d6b018cc40
Raw diff: https://github.com/php/php-src/commit/266c8d9975d01dbbe3a2d4429410b5d6b018cc40.diff

Merge branch 'PHP-8.4' into PHP-8.5

* PHP-8.4:
  Add a stack limit check in zend_hash_compare() (#23090)

Changed paths:
  A  Zend/tests/gh23088.phpt
  M  NEWS
  M  Zend/tests/gh18572.phpt
  M  Zend/zend_hash.c


Diff:

diff --git a/NEWS b/NEWS
index e99924f024ee..72388b5c946b 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,8 @@ PHP                                                                        NEWS
 
 - Core:
   . Fixed bug GH-22782 (Const expr FCC crashes under preloading). (Arnaud)
+  . Fixed bug GH-23088 (Stack overflow when comparing deeply nested arrays).
+    (Lazizbek Ergashev)
 
 - Date:
   . Fixed leak on double DatePeriod::__construct() call. (ilutov)
diff --git a/Zend/tests/gh18572.phpt b/Zend/tests/gh18572.phpt
index ff178ebef24f..cf45d2afaaba 100644
--- a/Zend/tests/gh18572.phpt
+++ b/Zend/tests/gh18572.phpt
@@ -36,4 +36,4 @@ try {
 }
 ?>
 --EXPECTREGEX--
-(Maximum call stack size reached during object comparison|Nesting level too deep - recursive dependency\?)
+(Maximum call stack size reached during (object )?comparison|Nesting level too deep - recursive dependency\?)
diff --git a/Zend/tests/gh23088.phpt b/Zend/tests/gh23088.phpt
new file mode 100644
index 000000000000..59153a1f2ba3
--- /dev/null
+++ b/Zend/tests/gh23088.phpt
@@ -0,0 +1,40 @@
+--TEST--
+GH-23088 (Stack overflow when comparing 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 = [];
+$b = [];
+
+for ($i = 0; $i < 20000; $i++) {
+    $a = [$a];
+    $b = [$b];
+}
+
+try {
+    var_dump($a == $b);
+} catch (Error $e) {
+    echo $e->getMessage(), PHP_EOL;
+}
+
+try {
+    var_dump($a === $b);
+} catch (Error $e) {
+    echo $e->getMessage(), PHP_EOL;
+}
+
+?>
+--EXPECT--
+Maximum call stack size reached during comparison
+Maximum call stack size reached during comparison
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index 7ec70e4e4971..b8c33548f930 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -3213,6 +3213,13 @@ ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t co
 		return 0;
 	}
 
+#ifdef ZEND_CHECK_STACK_LIMIT
+	if (UNEXPECTED(zend_call_stack_overflowed(EG(stack_limit)))) {
+		zend_throw_error(NULL, "Maximum call stack size reached during comparison");
+		return ZEND_UNCOMPARABLE;
+	}
+#endif
+
 	/* It's enough to protect only one of the arrays.
 	 * The second one may be referenced from the first and this may cause
 	 * false recursion detection.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.