Skip to content

Commit bafe8fe

Browse files
committed
Fix throwing behaviour with recursive arrays in VM
Behaviour change in 82479e8 overlooked this VM type spec optimization. The JIT had a follow-up already in a0a8624.
1 parent 06be15d commit bafe8fe

3 files changed

Lines changed: 46 additions & 7 deletions

File tree

‎Zend/zend_vm_def.h‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10022,11 +10022,11 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL|ZEND_IS_NOT_IDENTICAL, (op1_info
1002210022
ZEND_VM_SMART_BRANCH(result, 0);
1002310023
}
1002410024

10025-
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_IDENTICAL, op->op1_type == IS_CV && (op->op2_type & (IS_CONST|IS_CV)) && !(op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_REF)), ZEND_IS_IDENTICAL_NOTHROW, CV, CONST|CV, SPEC(COMMUTATIVE))
10025+
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_IDENTICAL, op->op1_type == IS_CV && (op->op2_type & (IS_CONST|IS_CV)) && !(op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !((op1_info & op2_info) & MAY_BE_ARRAY_OF_ARRAY), ZEND_IS_IDENTICAL_NOTHROW, CV, CONST|CV, SPEC(COMMUTATIVE))
1002610026
{
1002710027
/* This is declared below the specializations for MAY_BE_LONG/MAY_BE_DOUBLE so those will be used instead if possible. */
1002810028
/* This optimizes $x === SOME_CONST_EXPR and $x === $y for non-refs and non-undef, which can't throw. */
10029-
/* (Infinite recursion when comparing arrays is an uncatchable fatal error) */
10029+
/* Comparing two arrays that may contain arrays is excluded, as recursion throws an Error. */
1003010030
USE_OPLINE
1003110031
zval *op1, *op2;
1003210032
bool result;
@@ -10038,7 +10038,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_IDENTICAL, op->op1_type == IS_CV && (op->op2_t
1003810038
ZEND_VM_SMART_BRANCH(result, 0);
1003910039
}
1004010040

10041-
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_NOT_IDENTICAL, op->op1_type == IS_CV && (op->op2_type & (IS_CONST|IS_CV)) && !(op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_REF)), ZEND_IS_NOT_IDENTICAL_NOTHROW, CV, CONST|CV, SPEC(COMMUTATIVE))
10041+
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_NOT_IDENTICAL, op->op1_type == IS_CV && (op->op2_type & (IS_CONST|IS_CV)) && !(op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !((op1_info & op2_info) & MAY_BE_ARRAY_OF_ARRAY), ZEND_IS_NOT_IDENTICAL_NOTHROW, CV, CONST|CV, SPEC(COMMUTATIVE))
1004210042
{
1004310043
USE_OPLINE
1004410044
zval *op1, *op2;

‎Zend/zend_vm_execute.h‎

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
--TEST--
2+
IS_IDENTICAL/IS_NOT_IDENTICAL must not use the NOTHROW handler for arrays that may contain arrays
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.optimization_level=-1
7+
--EXTENSIONS--
8+
opcache
9+
--FILE--
10+
<?php
11+
function identical(array $a, array $b) {
12+
$r = $a === $b;
13+
echo "not reached\n";
14+
return $r;
15+
}
16+
17+
function not_identical(array $a, array $b) {
18+
$r = $a !== $b;
19+
echo "not reached\n";
20+
return $r;
21+
}
22+
23+
$x = [&$x];
24+
25+
try {
26+
identical($x, [[]]);
27+
} catch (Throwable $e) {
28+
echo $e::class, ": ", $e->getMessage(), "\n";
29+
}
30+
31+
try {
32+
not_identical($x, [[]]);
33+
} catch (Throwable $e) {
34+
echo $e::class, ": ", $e->getMessage(), "\n";
35+
}
36+
?>
37+
--EXPECT--
38+
Error: Nesting level too deep - recursive dependency?
39+
Error: Nesting level too deep - recursive dependency?

0 commit comments

Comments
 (0)