Category
stdlib
Problem
Under php-src-strict, string builtins must reject backed/unit enum case objects with TypeError (see #5780 hash family, #5861 ucfirst/nl2br sweep). lcfirst() still coerces enum cases via backing string on VM/JIT/AOT instead of raising:
TypeError: lcfirst(): Argument #1 ($string) must be of type string, E given
Sibling #5861 tracks ucfirst/nl2br/str_pad/addslashes; this issue is the lcfirst() gap verified independently.
php-src reference
Repro (verified 2026-06-05)
<?php
enum E: string { case A = 'hello'; }
try {
lcfirst(E::A);
echo "ok\n";
} catch (Throwable $t) {
echo get_class($t), ': ', $t->getMessage(), "\n";
}
docker info >/dev/null
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh
php8.2 repro.php
php bin/vm.php repro.php
php bin/jit.php repro.php 2>/dev/null || true
'
| Runtime |
Output |
| Zend PHP 8.2+ |
TypeError: lcfirst(): Argument #1 ($string) must be of type string, E given |
| vm.php today |
ok (silent coerce via backing string 'hello') |
Scope (PHP-in-PHP)
| Path |
Work |
ext/standard/lcfirst.php |
VM: VmString::coerceStringBuiltinArg() / EnumCaseSupport::isEnumCaseVariable() guard |
lib/JIT/JitStringBuiltinArg.php |
JIT/AOT: mirror VM guard (no C-only shortcut) |
test/compliance/cases/stdlib/lcfirst_enum_type_error.phpt |
VM compliance |
test/compliance/cases/stdlib/lcfirst_enum_type_error_jit.phpt |
JIT when LLVM available |
Do not add logic to runtime/*.c. Delete any C fast-path that bypasses enum-case rejection.
Done when
Related
Category
stdlibProblem
Under php-src-strict, string builtins must reject backed/unit enum case objects with
TypeError(see #5780 hash family, #5861 ucfirst/nl2br sweep).lcfirst()still coerces enum cases via backing string on VM/JIT/AOT instead of raising:Sibling #5861 tracks ucfirst/nl2br/str_pad/addslashes; this issue is the
lcfirst()gap verified independently.php-src reference
ext/standard/string.c—PHP_FUNCTION(lcfirst)—Z_PARAM_STRrejectsIS_OBJECTenum casesZend/zend_enum.c— enum case object typeRepro (verified 2026-06-05)
TypeError: lcfirst(): Argument #1 ($string) must be of type string, E givenok(silent coerce via backing string'hello')Scope (PHP-in-PHP)
ext/standard/lcfirst.phpVmString::coerceStringBuiltinArg()/EnumCaseSupport::isEnumCaseVariable()guardlib/JIT/JitStringBuiltinArg.phptest/compliance/cases/stdlib/lcfirst_enum_type_error.phpttest/compliance/cases/stdlib/lcfirst_enum_type_error_jit.phptDo not add logic to
runtime/*.c. Delete any C fast-path that bypasses enum-case rejection.Done when
TypeErroron VM (notok)php-src-strict; nophp-compiler-strictwithout proof)./script/ci-fast.sh --filter lcfirst_enumgreen.phptfiles added undertest/compliance/cases/stdlib/Related