Skip to content

Throw error for recursive comparison, instead of fatal #14989

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -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_*
Expand Down
11 changes: 8 additions & 3 deletions Zend/tests/bug63882.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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?
21 changes: 21 additions & 0 deletions Zend/tests/recursive_array_comparison.phpt
Original file line number Diff line number Diff line change
@@ -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)
3 changes: 2 additions & 1 deletion Zend/zend_hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion Zend/zend_object_handlers.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
Loading