Skip to content

Commit 82479e8

Browse files
authored
Throw error for recursive comparison, instead of fatal (#14989)
I don't understand the rationale of fatal erroring here. It seems this should properly unprotect the compared elements when returning up the stack. Related to GH-14980
1 parent e4d8699 commit 82479e8

File tree

6 files changed

+37
-5
lines changed

6 files changed

+37
-5
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ PHP NEWS
44

55
- Core:
66
. Fix GH-14978 (The xmlreader extension phpize build). (Peter Kokot)
7+
. Throw Error exception when encountering recursion during comparison, rather
8+
than fatal error. (ilutov)
79

810
- BCMath:
911
. Adjust bcround()'s $mode parameter to only accept the RoundingMode

UPGRADING

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ PHP 8.4 UPGRADE NOTES
3131
. The type of PHP_DEBUG and PHP_ZTS constants changed to bool.
3232
. The name of uploaded files and files created by the tempnam() function are
3333
now 13 bytes longer. Total length is platform-dependent.
34+
. Encountering recursion during comparison now results in a Error exception,
35+
rather than a fatal error.
3436

3537
- DOM:
3638
. Added DOMNode::compareDocumentPosition() and DOMNode::DOCUMENT_POSITION_*

Zend/tests/bug63882.phpt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ $testobj2 = new Test;
99
$testobj1->x = $testobj1;
1010
$testobj2->x = $testobj2;
1111

12-
var_dump($testobj1 == $testobj2);
12+
try {
13+
var_dump($testobj1 == $testobj2);
14+
} catch (Error $e) {
15+
echo $e->getMessage(), "\n";
16+
}
17+
1318
?>
14-
--EXPECTF--
15-
Fatal error: Nesting level too deep - recursive dependency? in %sbug63882.php on line 9
19+
--EXPECT--
20+
Nesting level too deep - recursive dependency?
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Comparison of a recursive array throws a catchable error
3+
--FILE--
4+
<?php
5+
$a = [&$a];
6+
try {
7+
$a === [[]];
8+
} catch (Error $e) {
9+
echo $e->getMessage(), "\n";
10+
}
11+
try {
12+
[[]] === $a;
13+
} catch (Error $e) {
14+
echo $e->getMessage(), "\n";
15+
}
16+
var_dump($a === $a);
17+
?>
18+
--EXPECT--
19+
Nesting level too deep - recursive dependency?
20+
Nesting level too deep - recursive dependency?
21+
bool(true)

Zend/zend_hash.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3180,7 +3180,8 @@ ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t co
31803180
* false recursion detection.
31813181
*/
31823182
if (UNEXPECTED(GC_IS_RECURSIVE(ht1))) {
3183-
zend_error_noreturn(E_ERROR, "Nesting level too deep - recursive dependency?");
3183+
zend_throw_error(NULL, "Nesting level too deep - recursive dependency?");
3184+
return ZEND_UNCOMPARABLE;
31843185
}
31853186

31863187
GC_TRY_PROTECT_RECURSION(ht1);

Zend/zend_object_handlers.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1985,7 +1985,8 @@ ZEND_API int zend_std_compare_objects(zval *o1, zval *o2) /* {{{ */
19851985
*/
19861986
/* use bitwise OR to make only one conditional jump */
19871987
if (UNEXPECTED(Z_IS_RECURSIVE_P(o1))) {
1988-
zend_error_noreturn(E_ERROR, "Nesting level too deep - recursive dependency?");
1988+
zend_throw_error(NULL, "Nesting level too deep - recursive dependency?");
1989+
return ZEND_UNCOMPARABLE;
19891990
}
19901991
Z_PROTECT_RECURSION_P(o1);
19911992

0 commit comments

Comments
 (0)