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
This commit is contained in:
Ilija Tovilo 2024-07-22 15:53:41 +02:00 committed by GitHub
parent e4d86998f6
commit 82479e89d0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 37 additions and 5 deletions

2
NEWS
View File

@ -4,6 +4,8 @@ PHP NEWS
- Core:
. Fix GH-14978 (The xmlreader extension phpize build). (Peter Kokot)
. Throw Error exception when encountering recursion during comparison, rather
than fatal error. (ilutov)
- BCMath:
. Adjust bcround()'s $mode parameter to only accept the RoundingMode

View File

@ -31,6 +31,8 @@ PHP 8.4 UPGRADE NOTES
. The type of PHP_DEBUG and PHP_ZTS constants changed to bool.
. The name of uploaded files and files created by the tempnam() function are
now 13 bytes longer. Total length is platform-dependent.
. Encountering recursion during comparison now results in a Error exception,
rather than a fatal error.
- DOM:
. Added DOMNode::compareDocumentPosition() and DOMNode::DOCUMENT_POSITION_*

View File

@ -9,7 +9,12 @@ $testobj2 = new Test;
$testobj1->x = $testobj1;
$testobj2->x = $testobj2;
var_dump($testobj1 == $testobj2);
try {
var_dump($testobj1 == $testobj2);
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
?>
--EXPECTF--
Fatal error: Nesting level too deep - recursive dependency? in %sbug63882.php on line 9
--EXPECT--
Nesting level too deep - recursive dependency?

View File

@ -0,0 +1,21 @@
--TEST--
Comparison of a recursive array throws a catchable error
--FILE--
<?php
$a = [&$a];
try {
$a === [[]];
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
try {
[[]] === $a;
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
var_dump($a === $a);
?>
--EXPECT--
Nesting level too deep - recursive dependency?
Nesting level too deep - recursive dependency?
bool(true)

View File

@ -3180,7 +3180,8 @@ ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t co
* false recursion detection.
*/
if (UNEXPECTED(GC_IS_RECURSIVE(ht1))) {
zend_error_noreturn(E_ERROR, "Nesting level too deep - recursive dependency?");
zend_throw_error(NULL, "Nesting level too deep - recursive dependency?");
return ZEND_UNCOMPARABLE;
}
GC_TRY_PROTECT_RECURSION(ht1);

View File

@ -1985,7 +1985,8 @@ ZEND_API int zend_std_compare_objects(zval *o1, zval *o2) /* {{{ */
*/
/* use bitwise OR to make only one conditional jump */
if (UNEXPECTED(Z_IS_RECURSIVE_P(o1))) {
zend_error_noreturn(E_ERROR, "Nesting level too deep - recursive dependency?");
zend_throw_error(NULL, "Nesting level too deep - recursive dependency?");
return ZEND_UNCOMPARABLE;
}
Z_PROTECT_RECURSION_P(o1);