Summary
hash_equals() must reject enum case objects with TypeError on both operands (Zend Z_PARAM_STR). This compiler coerces backed enum cases to backing strings and returns true, breaking timing-safe compare semantics.
php-src reference
ext/standard/hash.c — PHP_FUNCTION(hash_equals) (Z_PARAM_STR for $known_string and $user_string)
Repro
test/repro-maintainer/hash_equals_enum_operand.php:
enum E: string { case A = 'x'; }
var_export(hash_equals(E::A, 'x'));
| Runtime |
Output |
| Zend PHP 8.3 |
TypeError: hash_equals(): Argument #1 ($known_string) must be of type string, E given |
php bin/vm.php (this repo) |
true |
Expected fix (PHP-in-PHP)
Notes
Not covered by #5524 alone (umbrella string builtins); hash_equals is security-sensitive and currently has only scalar repros (#2179).
Summary
hash_equals()must reject enum case objects withTypeErroron both operands (ZendZ_PARAM_STR). This compiler coerces backed enum cases to backing strings and returnstrue, breaking timing-safe compare semantics.php-src reference
ext/standard/hash.c—PHP_FUNCTION(hash_equals)(Z_PARAM_STRfor$known_stringand$user_string)Repro
test/repro-maintainer/hash_equals_enum_operand.php:TypeError: hash_equals(): Argument #1 ($known_string) must be of type string, E givenphp bin/vm.php(this repo)trueExpected fix (PHP-in-PHP)
ext/standard/hash_equals.php— validateVariable::TYPE_ENUM_CASEand raiseTypeErrorbefore compare (mirror other string builtins; see also Stdlib: string builtins must TypeError on enum case operands (ext/standard/string.c) #5524 umbrella).lib/JIT/Builtin/handler forhash_equalsif enum operands reach native path.test/compliance/cases/stdlib/hash_equals_enum_operand.phptNotes
Not covered by #5524 alone (umbrella string builtins);
hash_equalsis security-sensitive and currently has only scalar repros (#2179).