Repository navigation
Conversation
|
Linux test (Arch, GCC 16.2.1, Release), head Require(pathconf_nid_postfix((directory + "/missing/" + std::string(256, 'n')).c_str(), 4) == -1 && Error() == 2);FreeBSD 11's |
3053b83 to
69b0c69
Compare
|
Thanks for measuring this, you are right. The up-front check in New head: the component length is checked only when every component before it exists and is a directory (otherwise the normal lookup answers AI-assisted (Claude Code). |
69b0c69 to
c48afd5
Compare
|
Follow-up to my comment of 13 October, 09:43Z, @nicolasfalesy: I ran the full The current head AI-assisted (Claude Code). |
stat, open, mkdir, rename and the other calls that resolve a guest path answered ENOENT (or EIO for rename) for a name longer than 255 bytes or a path of 1024 bytes or more, because the host path just did not exist. FreeBSD 11.4's namei fails a component above NAME_MAX and a path of MAXPATHLEN bytes with ENAMETOOLONG. Check both limits on the guest string before it is resolved; FilesystemError already maps the error to 63. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ONG instead of throwing Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…File exception among the path name length differences Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
c48afd5 to
b425544
Compare
|
Closing: no title is known to reach this. With the queue at 700+ open PRs, please hold off on new PRs that don't name a title needing the change until it's down. If a title stops on this on current main, reopen with the title ID and the log line. |
What
stat,open,mkdir,unlink,rmdir,rename,accessand the other calls that resolve a guest path answeredENOENT(andrenameEIO) for a path name that FreeBSD refuses as too long, because the resolved host path simply does not exist. FreeBSD 11.4'snameifails a path component aboveNAME_MAX(255 bytes) and a path ofMAXPATHLEN(1024 bytes including the terminating NUL) withENAMETOOLONG(63).Resolve()inGeneral.cpp(behindResolvePath_nid_no_patch) now checks the whole path (1024 bytes) on the guest string before resolving it, and a component above 255 bytes only when every component before it exists and is a directory (FreeBSD'snameiresolves in order, so a missing directory earlier in the path still answersENOENT); both throw afilesystem_errorwithfilename_too_long;FilesystemErroralready maps that to 63 andResolvePathError_nid_no_patch, which the kernel calls use, turns it into the errno. A name of exactly 255 bytes is not affected.A backslash counts as a path separator for the component length, because the guest path resolver turns it into
/before the host call; FreeBSD treats a backslash as an ordinary name character, so a name of 200 characters, a backslash and 100 more characters (301 bytes) is accepted here and refused by FreeBSD.Limits, listed in the TechnicalDebt entry for libc: the host's own limit still applies below these numbers (on Windows a path whose host form is longer than
MAX_PATHfails withENOENT), and a path through a regular file (file/x,file/) is still not alwaysENOTDIR; both are separate from this change.Not covered:
sceNgs2ParseWaveformFilecallsResolvePath_nid_no_patchwithout a try block, so a long component now ends in an uncaughtfilesystem_errorthere where a missing file ended inruntime_error("cannot open"); both end the title, it is not a regression, and it is not changed here. This and the backslash difference above are in the TechnicalDebt entry for libc (second commit).Callers of
ResolvePath_nid_no_patch/Resolve()(read again from the code onmain30f961266): theResolvePathError_nid_no_patchform catchesfilesystem_errorand returns the errno; the kernel and libc file calls use it (Open.cpp,Stdio.cpp,libkernel_sys/Export.cpp,Directory.cpp,FileAndHeap.cpp,RenameDot.hpp,Apr.cppand the AvPlayer, Font and LibcInternal path code). Direct callers of the throwing form:access,remove,chdir,renameandrealpathin libc (inside their try blocks, mapped byFilesystemError),dlopen(inside its try block,catch (const std::exception&)),chflagsin libkernelStdio.cpp(no try block; see below) andsceNgs2ParseWaveformFile(no try block, see above). The remaining direct callers pass fixed mount-point strings (libSceAppContent,libScePlayGo,libSceSaveData,AppMetadata) and cannot hit the new check.chflags(added tomainin 4dd97f7, after the first base of this branch) resolved its path with the throwing form and without a try block, so a long name would have ended the title once this check exists. The branch is rebased ontomain30f961266; its next commit makeschflagsuseResolvePathError_nid_no_patchlikechmod, andguest_path_name_lengthgains achflagscase (it fails without that commit with an uncaughtfilesystem_error).No title evidence: found by calling the file functions with oversized names (about 40 failure-path cases, of which 15 differed from FreeBSD; the others are not touched here). This is FreeBSD conformance.
Overlap (checked with
git merge-treeagainst the heads of #4796, #4920, #4922, #4929, #4968, #4989, #4993, #4999, #4532, #4681, #4743, #4817, #4870 and #4877): no conflict. The new test is registered next toguest_file_vector, away from the other test registrations in that file.Tested
Windows 10 (19045), MinGW-w64 GCC 15.2.0 (WinLibs r7), Release, first run on
main0f2683cb7(the re-run with the current head andmainis the bullet "Re-run on 14 October 2026" below):guest_path_name_length(new) passes:stat(first, final and only component of 256 bytes and a path of 1100 bytes),access,unlink,mkdir,rmdir,openand both arguments ofrenamefail withENAMETOOLONG; a name of exactly 255 bytes does not, in the final or in a middle component; a middle component of 256 bytes, a long name followed by a trailing slash, a path of exactly 1024 bytes fail and a path of exactly 1023 bytes does not; a long name below a missing directory givesENOENT.General.cpp(stat of a name above NAME_MAX (255) must fail with ENAMETOOLONG (63) (errno 2)).guest_kernel_sys(itspathconfcase with a missing directory before a 256-byte name must giveENOENT) and the other file, directory, path, realpath, working-directory, rename and stream tests pass with the change.python tools/check_conventions.py --base upstream/mainpasses.-j4), the headb425544c3merged ontomain7a0c838ca:guest_path_name_lengthpasses (0.51 s, ctest); withGeneral.cpptaken back tomainand the new test kept it fails (stat of a name above NAME_MAX (255) must fail with ENAMETOOLONG (63) (errno 2)). Second run, head merged ontomaind1670009f, the targets of the group built as well: onmainaloneguest_filesystem,guest_file_vector,guest_memory,guest_kernel_sys,guest_signalsandguest_directory_bufferpass (6 of 6); with the head and its test 7 of 7 pass, 0 failed. This replaces the earlier combined-build figures. Not run: the socket tests, Linux, a console, a title.chflags(second commit):guest_path_name_lengthalso callschflagswith a 256-byte name and requiresENAMETOOLONG; withStdio.cpptaken back tomainthe test ends in an uncaughtfilesystem_error(exit code0xc0000409);guest_filesystemandguest_kernel_syspass with the change (measured on the headb425544c3).Checklist
main; no other open PR implements the same functions (overlap described above)NotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt (docs/dev/debt/libc.md).mdfiles or images added to the repositoryAI-assisted (Claude Code).
🤖 Generated with Claude Code