Skip to content

Commit b693391

Browse files
committed
Fix enum to bool comparison
The compiler compiles $enum == true to ZEND_BOOL, which always returns true for objects (with the default cast_object handler). However, when compared to a statically unknown value $enum == $true, the resulting opcode ZEND_IS_EQUAL would call the objects compare handler. The zend_objects_not_comparable() handler, which is installed for enums and other internal classes, blanketly returns false. This does not match the ZEND_BOOL semantics. We now handle bools in zend_objects_not_comparable() explicitly. Fixes GH-16954
1 parent 51e0920 commit b693391

File tree

3 files changed

+59
-2
lines changed

3 files changed

+59
-2
lines changed

Zend/tests/enum/comparison.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,5 +53,5 @@ bool(false)
5353
bool(false)
5454
bool(false)
5555
bool(false)
56-
bool(false)
57-
bool(false)
56+
bool(true)
57+
bool(true)

Zend/tests/gh16954.phpt

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
--TEST--
2+
GH-16954: Enum to bool comparison is inconsistent
3+
--FILE--
4+
<?php
5+
6+
enum E {
7+
case C;
8+
}
9+
10+
$true = true;
11+
$false = false;
12+
13+
var_dump(E::C == true);
14+
var_dump(E::C == $true);
15+
var_dump(true == E::C);
16+
var_dump($true == E::C);
17+
18+
var_dump(E::C != true);
19+
var_dump(E::C != $true);
20+
var_dump(true != E::C);
21+
var_dump($true != E::C);
22+
23+
var_dump(E::C == false);
24+
var_dump(E::C == $false);
25+
var_dump(false == E::C);
26+
var_dump($false == E::C);
27+
28+
var_dump(E::C != false);
29+
var_dump(E::C != $false);
30+
var_dump(false != E::C);
31+
var_dump($false != E::C);
32+
33+
?>
34+
--EXPECT--
35+
bool(true)
36+
bool(true)
37+
bool(true)
38+
bool(true)
39+
bool(false)
40+
bool(false)
41+
bool(false)
42+
bool(false)
43+
bool(false)
44+
bool(false)
45+
bool(false)
46+
bool(false)
47+
bool(true)
48+
bool(true)
49+
bool(true)
50+
bool(true)

Zend/zend_object_handlers.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1819,6 +1819,13 @@ ZEND_API int zend_std_compare_objects(zval *o1, zval *o2) /* {{{ */
18191819

18201820
ZEND_API int zend_objects_not_comparable(zval *o1, zval *o2)
18211821
{
1822+
zval *other = Z_TYPE_P(o1) == IS_OBJECT ? o2 : o1;
1823+
1824+
/* Fall back to zend_std_compare_objects() for bool. */
1825+
if (Z_TYPE_P(other) == IS_TRUE || Z_TYPE_P(other) == IS_FALSE) {
1826+
return zend_std_compare_objects(o1, o2);
1827+
}
1828+
18221829
return ZEND_UNCOMPARABLE;
18231830
}
18241831

0 commit comments

Comments
 (0)