Skip to content

fix(libkernel): fail sce path calls with ENAMETOOLONG for a path of 1024 bytes or more - #14874

Merged
oneandonlydean merged 1 commit into
boykopovar:mainfrom
roboterspinne:fix/libkernel-path-name-too-long-errors
Nov 3, 2026
Merged

oneandonlydean merged 1 commit into
boykopovar:mainfrom
roboterspinne:fix/libkernel-path-name-too-long-errors

Conversation

@roboterspinne

Copy link
Copy Markdown
Contributor

What

On e0caf13 (line numbers below refer to it) a guest path with no NUL in its first 1024 bytes makes sceKernelStat, sceKernelUnlink, sceKernelMkdir, sceKernelRmdir, sceKernelChmod, sceKernelTruncate and sceKernelUtimes return SCE_KERNEL_ERROR_EIO (0x80020005) on Windows (run) and, by the same mapping, on Linux (not run). CopyGuestPath_nid_no_patch returns the guest errno 63 (ENAMETOOLONG) for such a path (core/libs/prx/libc/src/General.cpp:570 and 574), but these seven callers pass it to SceErrorFromErrno (core/libs/prx/libkernel/File/src/Open.cpp:461 and 482; core/libs/prx/libkernel/File/src/Stdio.cpp:1349, 1646, 1690, 1730 and 1768), which maps host errnos: values 1 to 34 pass through, and 63 is not host ENAMETOOLONG on MinGW (38) or Linux (36), so Stdio.cpp:509 and FilesystemError behind Open.cpp:185 turn it into EIO. Only on macOS, where host ENAMETOOLONG is 63, does the mapping give the right code (derived from the code, not run). FreeBSD's namei copies the path with copyinstr(..., MAXPATHLEN, ...) and fails with ENAMETOOLONG when no NUL fits in 1024 bytes (sys/kern/vfs_lookup.c), and the repository already returns SceKernelError(error) for the same copy failure in sceKernelOpen (Open.cpp:300) and sceKernelCheckReachability (Stdio.cpp:1162); the POSIX wrappers already set errno 63 for these paths, as core/libs/tests/GuestPathNameLength.cpp checks for stat. The seven call sites came in with 2c5fcf6, which used SceKernelError only in sceKernelOpen and sceKernelCheckReachability.

Tested

Windows 11, WinLibs GCC 15.2.0, full configuration (Ninja, Release, BUILD_TESTING=ON; built targets: guest_path_name_length_tests with libkernel, and the related test targets below), on 2de34f8 (based on e0caf13; main at 5bae1a4 changed none of these files and merges cleanly):

  • Counter-check: with the new test and the unchanged Open.cpp and Stdio.cpp of e0caf13, cmake --build build --target guest_path_name_length_tests and build/tests/guest_path_name_length_tests.exe abort with the sce path calls must fail a path of exactly 1024 bytes with SCE_KERNEL_ERROR_ENAMETOOLONG: sceKernelStat returned 0x80020005. The helper stops at the first wrong result; the other six calls go through the same SceErrorFromErrno mapping.
  • With the change: ctest --test-dir build -R '^guest_path_name_length$' --output-on-failure passed (0.04 s), and the executable run directly exits 0.
  • Related tests, rebuilt with the change: ctest --test-dir build -R '^(guest_path_name_length|guest_filesystem|guest_filesystem_error|guest_file_timestamps|guest_truncate|guest_truncate_extend|guest_rename_dot|guest_directory)$' --output-on-failure: 8 of 8 passed.
  • python tools/check_conventions.py --base e0caf13600 --head HEAD with this title and description passed.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: yes (Claude Code)

@github-actions

github-actions Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 5021 core/libs/prx/libkernel/File/src/Open.cpp
core/libs/prx/libkernel/File/src/Stdio.cpp
PR 6936 core/libs/prx/libkernel/File/src/Open.cpp
core/libs/prx/libkernel/File/src/Stdio.cpp
PR 7121 core/libs/prx/libkernel/File/src/Open.cpp
core/libs/prx/libkernel/File/src/Stdio.cpp
PR 7447 core/libs/prx/libkernel/File/src/Stdio.cpp
PR 9019 core/libs/prx/libkernel/File/src/Open.cpp
core/libs/prx/libkernel/File/src/Stdio.cpp
PR 9293 core/libs/prx/libkernel/File/src/Stdio.cpp
PR 9297 core/libs/prx/libkernel/File/src/Stdio.cpp
PR 9302 core/libs/prx/libkernel/File/src/Stdio.cpp
PR 10319 core/libs/prx/libkernel/File/src/Open.cpp
PR 11831 core/libs/prx/libkernel/File/src/Open.cpp
core/libs/prx/libkernel/File/src/Stdio.cpp
PR 12560 core/libs/prx/libkernel/File/src/Open.cpp
core/libs/prx/libkernel/File/src/Stdio.cpp
PR 12682 core/libs/prx/libkernel/File/src/Open.cpp
core/libs/prx/libkernel/File/src/Stdio.cpp
PR 12688 core/libs/prx/libkernel/File/src/Open.cpp
core/libs/prx/libkernel/File/src/Stdio.cpp
PR 12700 core/libs/prx/libkernel/File/src/Open.cpp
core/libs/prx/libkernel/File/src/Stdio.cpp
PR 12965 core/libs/prx/libkernel/File/src/Open.cpp
core/libs/prx/libkernel/File/src/Stdio.cpp

@BunnyFl BunnyFl left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed at 2de34f87bf, merged locally into main 66e1f7f993 (clean merge; GitHub reports it mergeable). Windows 11 Pro 10.0.26300, WinLibs GCC 15.2.0, Release, Ninja.

The bug is as described. CopyGuestPath_nid_no_patch returns guest errnos: 14 for a null or unreadable source, 12 for an allocation failure and 63 for no NUL within 1024 bytes (CopyGuestString_nid_no_patch(source, 1024, ...)). Both SceErrorFromErrno mappers take host errnos:

  • Stdio.cpp passes 1 to 34 through and maps the host ENAMETOOLONG (38 on MinGW, 36 on Linux), so guest 63 falls through to GUEST_EIO.
  • Open.cpp passes 1 to 34 through and sends anything else to FilesystemError as a host std::generic_category code.

SceKernelError(e) is 0x80020000 | e, so 12 and 14 give the same results as before, and 63 now gives SCE_KERNEL_ERROR_ENAMETOOLONG, as sceKernelOpen already does.

What I ran

  • ctest -R '^guest_path_name_length$' --repeat until-fail:3: passes, 3 of 3.
  • Negative control: main's Open.cpp and Stdio.cpp with this PR's test: fails with the sce path calls must fail a path of exactly 1024 bytes with SCE_KERNEL_ERROR_ENAMETOOLONG: sceKernelStat returned 0x80020005.
  • python tools/check_conventions.py --base upstream/main: passes.

Looks good.

AI-assisted: yes (Claude Code)

@oneandonlydean oneandonlydean self-assigned this Nov 3, 2026
@oneandonlydean
oneandonlydean merged commit 165d818 into boykopovar:main Nov 3, 2026
12 checks passed
@roboterspinne
roboterspinne deleted the fix/libkernel-path-name-too-long-errors branch November 3, 2026 10:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants