Category
stdlib
Problem
Several path-string builtins accept enum case operands on VM (treating them as paths or coercing silently) while Zend throws TypeError. php-src-strict: reject TYPE_ENUM_CASE before any path coercion — never pass backing string/name to open()/stat().
Phase 1 (this issue): read/stat family below. Phase 2: #6205 (filesize, disk_*, chmod, touch, fopen, …). Phase 3: #6280 / #6266 (copy, rename, link, …).
php-src reference
Repro (verified 2026-06-05)
<?php
enum PathEnum: string { case A = 'x'; }
enum UnitEnum { case A; }
$fns = [
'file_get_contents', 'file_exists', 'is_file', 'is_dir', 'is_link',
'is_readable', 'is_writable', 'is_executable', 'unlink', 'mkdir', 'rmdir',
];
foreach ($fns as $fn) {
if (!function_exists($fn)) {
echo "{$fn} missing\n";
continue;
}
try {
$fn(PathEnum::A);
echo "{$fn} ok\n";
} catch (Throwable $e) {
echo "{$fn} " . $e::class . ': ' . $e->getMessage() . "\n";
}
}
docker info >/dev/null
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh
php repro.php
php bin/vm.php repro.php
'
| Function |
Zend PHP 8.2 |
bin/vm.php (today) |
file_get_contents |
TypeError |
succeeds ❌ |
file_exists |
TypeError |
succeeds ❌ |
is_file |
TypeError |
succeeds ❌ |
is_dir |
TypeError |
succeeds ❌ |
unlink |
TypeError |
succeeds ❌ |
mkdir |
TypeError |
succeeds ❌ |
Use backed and unit enum cases in compliance .phpt; message must name enum class (not "string expected").
Scope (PHP-in-PHP)
| Layer |
Path |
| VM shared guard |
ext/standard/VmString.php — coerceStringBuiltinArg() / new rejectEnumCasePathArg() before IO |
| Per-builtin |
ext/standard/file_get_contents.php, file_exists.php, is_*.php, unlink.php, mkdir.php, … |
| JIT |
JitFileGetContents.php, JitFileExists.php, … — emit TypeError before phpc_fs_dir.c / stream helpers |
| C shrink |
Keep phpc_fs_dir.c thin per #5459; guards live in PHP lowering |
Mirror #5780 hash enum guard pattern for VM + JIT + AOT when touched.
Done when
Verification
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && vendor/bin/phpunit --filter fs_path_enum_operand'
Related
Category
stdlibProblem
Several path-string builtins accept enum case operands on VM (treating them as paths or coercing silently) while Zend throws
TypeError. php-src-strict: rejectTYPE_ENUM_CASEbefore any path coercion — never pass backing string/name toopen()/stat().Phase 1 (this issue): read/stat family below. Phase 2: #6205 (
filesize,disk_*,chmod,touch,fopen, …). Phase 3: #6280 / #6266 (copy,rename,link, …).php-src reference
ext/standard/filestat.c—php_file_exists,php_is_file,php_is_dir,php_is_link,php_is_readable,php_is_writableext/standard/streamsfuncs.c—php_file_get_contentsext/standard/file.c—php_unlink,php_mkdir,php_rmdirZ_PARAM_STR/zend_parse_parametersrejects objects — enum cases are objects in PHP 8.1+Repro (verified 2026-06-05)
bin/vm.php(today)file_get_contentsTypeErrorfile_existsTypeErroris_fileTypeErroris_dirTypeErrorunlinkTypeErrormkdirTypeErrorUse backed and unit enum cases in compliance
.phpt; message must name enum class (not"string expected").Scope (PHP-in-PHP)
ext/standard/VmString.php—coerceStringBuiltinArg()/ newrejectEnumCasePathArg()before IOext/standard/file_get_contents.php,file_exists.php,is_*.php,unlink.php,mkdir.php, …JitFileGetContents.php,JitFileExists.php, … — emit TypeError beforephpc_fs_dir.c/ stream helpersphpc_fs_dir.cthin per #5459; guards live in PHP loweringMirror #5780 hash enum guard pattern for VM + JIT + AOT when touched.
Done when
TypeErroron VM (skipmissingwith note in PR)test/compliance/cases/stdlib/fs_path_enum_operand.phpt— VM + JIT rows when loweredopen()/stat()on coerced enum backing values./script/ci-fast.sh --filter fs_path_enum_operandgreenVerification
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && vendor/bin/phpunit --filter fs_path_enum_operand'Related