Prevent reached null conversion destinations from crashing sscanf_s and vsscanf_s. Return EOF before writes and retain earlier assignments. Add regression coverage through both guest ABI entry points.
AI-assisted: yes (OpenAI Codex). Windows WinLibs GCC 15.2 Release: production baseline crashes with the new regression; fixed shared libc passes guest_scan_count, guest_formatting, guest_wide_formatting and guest_strings (4/4). Conventions pass. Full all-target build was deliberately stopped after 83s with 3691 pending targets, not completed. No title or console run; constraint-handler invocation remains unimplemented as documented. No performance or coverage-percentage claim.
fopen_s returned ENOENT for every failed open, including an invalid mode, a directory opened for writing and the loop and long-name cases. C11 K.3.5.2.1 only asks for a nonzero value; Microsoft's CRT, which shares Dinkumware's library, returns errno. fopen_s now returns the errno fopen set.
PPSA28997 (IL2CPP) calls sceLibcBacktraceGetBufferSize and
sceLibcBacktraceSelf. On Linux the host call stack is captured with
backtrace and each frame is resolved to its module and offset with
dladdr, then written as a linked list of frame records. The record
layout is inferred and listed in TechnicalDebt. Windows throws.
A ZArchive named app0.zar beside app0/ is a read-only layer under it. libc opens it at the first path resolution, looks paths missing from app0/ up case-insensitively, reads files across compressed blocks and keeps the archived descriptor table with shared positions.
Resolving an archive-only path through a call that does not read the archive throws instead of failing with ENOENT, as do opendir of a directory present in both places, fdopen of an archived descriptor and chdir into the archive. A path through .. in an archive-only directory resolves.
Use the registered application allocator and the source-backed alignment/size signature. Add callback ownership and failure checks; record unmeasured console behavior.
Implement __modti3, the signed 128-bit integer modulo runtime helper complementing __divti3, __udivti3 and __umodti3. Add unit test coverage in guest_crt_tests and document zero-divisor exception behavior in technical debt.
Borderlands 4 (PPSA01494) loads its UI library with
sceKernelLoadStartModule("/app0/prx/libRenoirCore.PS5.prx"), but ships
the module as prx/librenoircore.ps5.prx. On Linux the call fails:
Could not load /app0/prx/libRenoirCore.PS5.prx result 0, handle result -2147352574
(0x80020002, ENOENT). Guest paths are resolved case-insensitively, but
that only finds a component that exists. With the documented layout,
app0/prx holds only the converted librenoircore.ps5.prx.guest.prx,
so the requested name resolves to itself and RelinkedModulePath then
looks for "libRenoirCore.PS5.prx.guest.prx" with its exact spelling.
Windows and macOS hosts ignore the case, so only Linux is affected.
RelinkedModulePath now falls back to the same ASCII case-insensitive
match as ResolveHostPath when the exact <name>.guest.prx is missing,
and throws for an ambiguous match as that does. dlopen,
sceKernelLoadStartModule, stat, open and sceKernelCheckReachability all
go through it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Guest path resolution trimmed the trailing slash of a path under a
mount alias (/savedata0, /download0, /app0 and the others), so the host
saw "file" for "file/": unlink, remove, sceKernelUnlink and rename
removed or moved the file, open opened it, and chmod and access
succeeded on it. The same path outside an alias already failed with
ENOTDIR, because the host got the slash.
FreeBSD 11.4 rejects it in lookup() (sys/kern/vfs_lookup.c):
/*
* If we're processing a path with a trailing slash,
* check that the end result is a directory.
*/
if ((cnp->cn_flags & TRAILINGSLASH) && dp->v_type != VDIR) {
error = ENOTDIR;
goto bad2;
}
On Linux and macOS a path under an alias now keeps its trailing slash
on the host path, as paths outside an alias do, so the host fails with
ENOTDIR for a file and directories with a trailing slash still work.
Windows keeps the previous behaviour; TechnicalDebt records it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Add the missing wide secure formatting exports required by PPSA15552
(Dead Cells), whose load failed with `undefined symbol: Im55VJ-Bekc`:
swprintf_s and its va_list counterpart follow C11 Annex K.3.9.1.4
(the complete output, including the terminator, must fit), while
vsnwprintf_s is the va_list counterpart of snwprintf_s (K.3.9.1.3,
truncation with full length). The export names produce NIDs
Im55VJ-Bekc, oDoV9tyHTbA and 8SKVXgeK1wY respectively. Document
the new functions in docs/dev/debt/libc.md.