[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.