Commit Graph
57 Commits
Author SHA1 Message Date
JJenkxandClaude Opus 5.5 afa58432f3 fix(libc): format %La like titles' libc.prx does
A long double %La went to the host, which on Windows (MinGW) prints the
64-bit significand with its integer bit as the leading digit:
0xc.ccccccccccccccdp-7 for 0.1L. The libc.prx that titles ship
normalises it like a double, with a leading 1 and the remaining 63 bits
as 16 hexadecimal digits, 0x1.999999999999999ap-4, and rounds a shorter
precision half up with the carry kept in the leading digit. Share
HexFloat's digit and rounding code between double and long double and
use it for finite long double %a and %A in the narrow and wide families.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 08:52:35 -04:00
Adrià 91a5573911 Merge pull request #9479 from EagleBearerYS/fix/libc-scanf-integer-widths-windows
fix(libc): convert scanf integers as FreeBSD does on Windows
2026-10-25 20:52:26 +01:00
Dean 5e675163f0 Merge pull request #9916 from JJenkx/windows/printf-decimal-console
fix(libc): round and cap %e, %f and %g as titles' libc.prx does
2026-10-26 04:45:09 +13:00
boykopovar f38d29fd08 refactor(sdk): add canonical headers for remaining libraries 2026-10-24 23:17:42 +03:00
JJenkxandClaude Opus 5.5 182bd6aa78 fix(libc): round and cap %e, %f and %g as titles' libc.prx does
The printf family formatted floating-point conversions through the host,
which prints every exact digit and rounds ties to even. The libc.prx
that titles ship keeps the exact digits only down to a position derived
from the binary exponent and prints zeros after them, rounds half up on
the kept digits, and rounds an exact tie down once that exponent
estimate reaches 8. So %.0f of 2.5 is 3 and %.1f of 0.25 is 0.3 there,
and %.20f of 0.1 is 0.10000000000000000555.

Format finite double and long double e, f and g conversions with those
rules from exactly generated digits, on every host. On 600,000 random
formats every output with up to 17 significant digits now matches the
copies bundled with PPSA07923, PPSA05916 and PPSA13934; longer outputs
still differ where the console's extended-precision digits end one unit
lower.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 16:17:13 -04:00
JJenkx 1a610d2f25 fix(libc): bound hex float allocation by remaining output 2026-10-24 16:14:15 -04:00
JJenkx a8c040004f fix(libc): reject oversized hex float output before allocation 2026-10-24 16:14:15 -04:00
JJenkx e2d2d5171b fix(libc): reject overflowing hex float precision 2026-10-24 16:14:15 -04:00
JJenkxandClaude Opus 5.5 1fbd44b66f fix(libc): format %a like the console on Windows
The Windows printf family handed %a and %A to the host, whose UCRT prints
a subnormal unnormalised (0x0.0000000000001p-1022) and pads with zeros
even when the - flag is given (%-010a of 1.5 gave 0x001.8p+0). The
libc.prx that titles ship normalises subnormals (0x1p-1074), rounds a
shorter precision half up without renormalising a carry, and lets -
override 0, as C requires.

Finite doubles are now formatted here, checked against three titles'
copies of libc.prx run side by side.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 16:14:15 -04:00
orezraeyandClaude Opus 5.5 30f054270f test(libc): keep only the measured unknown-conversion printf cases
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 14:31:14 -03:00
orezraeyandClaude Opus 5.5 2f99b411af Merge main into fix/libc-printf-measured-ps5
Keep #3987's q, D, O, U, width, '-' and trailing '%' handling for
unknown conversions and fold it into this branch's measured path:
'#' and precision are ignored as measured, '+', space, apostrophe
and '0' with a width still throw.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 13:33:52 -03:00
Adrià Franch a5e60928ec test(libc): fix expected length of the printf unknown conversion case 2026-10-24 10:22:18 +02:00
MarcZX10 a3e41499be fix(libc): match title printf conversions on Windows 2026-10-24 10:22:15 +02:00
MarcZX10 11fc4b3e1a fix(libc): resolve printf rebase conflicts 2026-10-24 10:22:15 +02:00
MarcZX100 87cf00de0d test(libc): drop printf formats now supported on main 2026-10-24 10:22:15 +02:00
MarcZX100 45bfa20e43 test(libc): separate Windows printf conversion cases 2026-10-24 10:22:15 +02:00
Hussein Kadhim b331e3a86d fix(libc): keep throwing for printf conversions FreeBSD supports but Windows does not
The unknown-conversion branch printed %m, positional arguments, the grouping
flag and modifiers in an unusual order as literal characters. Only characters
FreeBSD's vfprintf prints as themselves are now printed.

(cherry picked from commit 0106858d3d39f83eb2234a5f581d5bf5260521a0)
2026-10-24 10:22:15 +02:00
Hussein Kadhim 621a487bdf fix(libc): print the FreeBSD printf extensions and stray percent signs on Windows
The Windows printf family threw on the q length modifier, the D, O and U
conversions, an unknown conversion character and a format ending in a percent
sign, where FreeBSD's vfprintf formats the first three and prints the unknown
character itself or stops at the end of the format.

(cherry picked from commit 0e3b2896d228c601cefc992b2895723188ebf0fa)
2026-10-24 10:22:15 +02:00
Yunus Shaikh a809ad7d2f fix(libc): fail a q length in scanf as the console's libc does
The console's own sscanf, run natively from three titles' libc.prx, returns 0 for %qd and stores nothing, where FreeBSD 11.4's source reads q as ll. A q directive now ends the scan there, and the count of conversions before it is returned. The test adds the console's rows for wrapping narrow conversions, saturating 64-bit ones with ERANGE, and %qd.
2026-10-23 19:26:15 -07:00
Dean 999e612599 Merge pull request #4627 from mugurc/fix/libc-macos-host
fix(libc): build the host-facing libc code on macOS
2026-10-24 11:50:45 +13:00
orezraeyandClaude Opus 5.5 33f1d7ec43 fix(libc): format sizes, NaN signs, UTF-16 units, positions and unknown conversions as a PS5 does
Measured through libSceLibcInternal.sprx's snprintf in a payload process on a PS5 (firmware 13.60): any size is accepted, a NaN keeps its sign and the + and space flags, each UTF-16 unit of %ls and %lc is encoded alone, positions above 99 work, and an unknown conversion such as %m prints % and its letter.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-23 11:20:47 -03:00
mugurc c27787a7db fix(libc): build the host-facing libc code on macOS
feof_unlocked, ferror_unlocked, getc_unlocked and putc_unlocked are macros
on macOS, so they are called without the global scope qualifier. The
remaining differences are the ones Darwin's headers and libSystem have:

- CLOCK_REALTIME_COARSE and st_mtim do not exist; the write mark uses
  CLOCK_REALTIME and st_mtimespec.
- tm_zone is a non-const char*.
- __cxa_thread_atexit returns void, so the wrapper reports success.
- Darwin's stack protector reads __stack_chk_guard from libSystem; the
  guard of the guest libc has the postfixed name, which receives the NID
  of the original.
- APS5_EXPORT spells the symbols with the leading underscore of Mach-O.
- GuestArenaSetProtection and PosixProtection are built on macOS as on Linux.
- The fclose failure test fills /dev/full, which exists on Linux only.

exception_runtime relies on the Itanium unwinder of libc, which is not
registered on macOS (the host libc++abi is used), so its test is only
registered elsewhere.
2026-10-22 12:25:14 +03:00
Yunus Shaikh b39956b4e1 fix(libc): keep the signedness of narrow scanf conversions on Windows
A %u, %o or %x scanned through the 64-bit temporary now writes an unsigned long long and is stored through an unsigned destination, as the rewritten %llu, %llo and %llx require.
2026-10-21 16:04:54 -07:00
Yunus Shaikh 1994558954 Merge main into fix/libc-scanf-integer-widths-windows 2026-10-21 15:29:12 -07:00
Superhe11 eecffc924b test(libc): cover snprintf size bounds and formatting side effects 2026-10-21 20:34:41 +03:00
xXPBSXxandClaude Sonnet 5.5 acf96f32d0 fix(libc): fail snprintf and vsnprintf with EOVERFLOW when the size exceeds INT_MAX
FreeBSD 11.4 vsnprintf checks the size minus the terminator against INT_MAX
before formatting and, when it is larger, sets errno to EOVERFLOW, writes a
terminator to the buffer and returns EOF (lib/libc/stdio/vsnprintf.c:61-67).
The guest formatted into the buffer and returned the length.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-21 20:34:41 +03:00
Alexej Szpevák 675ff30898 feat(libc): scan 16-bit wide conversions in the sscanf family on Linux
sscanf, vsscanf, sscanf_s and vsscanf_s threw on Linux for %ls, %lc, %l[, %S and %C, because glibc stores a 32-bit wchar_t per character into the guest's 16-bit buffer. ScanGuest, the per-directive scanner the _s forms already use, now scans those fields itself: the input is decoded as UTF-8, mirroring the narrow printf family's UTF-8 output, and each character is stored as one 16-bit unit, the width and the _s size counting characters; %ls skips leading white space and stops at the next, %l[ matches an ASCII scanset with ranges and negation, and a %lc field that meets the end of the input early keeps what it read, as FreeBSD's convert_wchar does. sscanf and vsscanf route a format with a wide conversion through ScanGuest and keep the host path otherwise. The UTF-8 decoding and scanset matching live in ScanWideField.cpp, which throws for input that is not UTF-8, a character outside the BMP, a scanset member outside ASCII and positional arguments next to a wide conversion; wide conversions in fscanf still throw.
2026-10-19 22:30:07 +02:00
hypermistandClaude Opus 5.5 e9f4dbfcf5 fix(libc): check the C11 runtime constraints in snprintf_s and vsnprintf_s
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-18 23:43:55 +02:00
Slick Daddy 536fef3228 fix(libc): format %p the way the console's libc does
The console's libSceLibcInternal.sprx (measured on firmware 12.70 in
#7549) prints %p as bare lowercase hex without a 0x prefix, prints 0 for
a null pointer, ignores #, + and the space flag, counts only the digits
towards the width, pads with spaces on the left (on the right for - and
with zeros for 0 when there is no precision), treats the precision as
the minimum number of digits, prints nothing for a null pointer under
%.0p, and accepts the l length. FormatPointer instead followed FreeBSD
and printed 0x..., which is what a title does not see on hardware.

FormatPointer now prints the digits alone, the narrow Windows formatter
accepts %lp, and Linux routes %p and %lp to the guest formatter instead
of glibc, which prints the FreeBSD form and (nil) for a null pointer.
The wide family still refuses %lp, because the console's swprintf was
not measured with it; it returns -1 as it does for any other conversion
the formatter rejects. The debt note records the pointer cases the
console was not measured with and what the Linux routing means for a
format that mixes %p with a refused conversion.
2026-10-18 16:59:34 +03:00
Muhammad Wasif Ali WasifandClaude Opus 5.5 9d9554948c fix(libc): ignore the space and + flags for unsigned printf conversions
The guest formatter passed the flags of %o, %u, %x and %X to the host, and
MinGW's printf prefixes a space to %u when the space flag is set: "% u" of 5
gave " 5". C17 7.21.6.1 applies both flags to signed conversions only, and
FreeBSD 11.4 vfprintf clears the sign for every unsigned conversion (nosign).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 15:03:45 +05:00
Yunus Shaikh a7f3f9cff1 test(libc): run CheckIntegerScanWidths from RunChecks
#5070 adds its own check before main() and rewrites the one-line main(), so defining CheckIntegerScanWidths there and calling it from main() made the two pull requests conflict. It now sits before RunChecks and runs after the other scanf checks.
2026-10-13 03:40:45 -07:00
Claude 13444c82e9 fix(libc): print NaN without a sign in the guest printf formatter
The guest formatter handed NaN to the host's snprintf, which prints
-nan for a negative NaN and +nan or " nan" with the + and space flags.
FreeBSD 11's vfprintf clears the sign of every NaN and prints nan (NAN
for the upper-case conversions), keeping the width and the - flag and
ignoring 0. The formatter now does the same for a, e, f and g and
their long double forms.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01VZWLdTjf1S57iLgn2rcaFb
2026-10-13 08:26:41 +00:00
Yunus Shaikh 8d0f209a8a fix(libc): convert scanf integers as FreeBSD does on Windows 2026-10-12 15:32:16 -07:00
Dean 655cba83d5 Merge pull request #4358 from milescoviello/fix/scanf-binary-prefix
fix(libc): read %i without the C23 binary prefix in the scanf family on Linux
2026-10-13 07:19:26 +13:00
Dean bde332a59c Merge pull request #4353 from milescoviello/fix/printf-errno-message
fix(libc): print the guest errno message for %m in the printf family
2026-10-13 07:18:29 +13:00
milescovielloandClaude Opus 5.5 89bc9d1082 fix(libc): read %i without the C23 binary prefix in the scanf family on Linux
On Linux sscanf, vsscanf, fscanf and sscanf_s hand their conversions to
glibc. Since glibc 2.38, code built as GNU C++ calls the C23 entry
points (__isoc23_vsscanf, __isoc23_vfscanf, __isoc23_sscanf), whose %i
reads a 0b/0B binary prefix. On main,
sscanf("0b101 x", "%i%n%7s", &value, &end, rest) stores value 5 and
end 5 and leaves "x" for the %s; " -0B11" gives -3. TechnicalDebt
records this.

FreeBSD's %i knows only the 0 and 0x prefixes. FreeBSD 11.4
lib/libc/stdio/vfscanf.c, parseint, lines 345-353 and 371-380:

	case '0':
		if (base == 0) {
			base = 8;
			flags |= PFXOK;
		}
	...
	/* letters ok iff hex */
	case 'A': case 'B': case 'C':
	case 'D': case 'E': case 'F':
	case 'a': case 'b': case 'c':
	case 'd': case 'e': case 'f':
		/* no need to fix base here */
		if (base <= 10)
			break;	/* not legal here */

so "0b101" stores 0, consumes the "0" and leaves "b101", as C17 does
and as the strtol family here already does.

With glibc the scanf family now calls __isoc99_vsscanf and
__isoc99_vfscanf, the entry points GNU C++ used before glibc 2.38
(exported since 2.7), which read %i without the binary prefix. Other
hosts keep std::vsscanf and std::vfscanf. The TechnicalDebt entry is
removed.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 08:38:06 +00:00
Dean 0511e86de9 Merge pull request #3984 from zmeizy/claude/scanf-wide-linux
fix(libc): throw for 16-bit wide scanf conversions on Linux
2026-10-12 21:37:08 +13:00
milescovielloandClaude Opus 5.5 4ece6750b7 fix(libc): print the guest errno message for %m in the printf family
FreeBSD's printf formats %m as the message for the errno value at the
time of the call. On Linux a format with %m went to glibc, which looks
the number up in Linux's table, so guest errno values above 34 got
another error's text: with errno 35 (EAGAIN) "[%m]" printed
"[Resource deadlock avoided]" instead of "[Resource temporarily
unavailable]", and errno 63 (ENAMETOOLONG) printed "Out of streams
resources". On Windows, and on Linux when the format also had a wide
argument, the guest formatter threw on %m.

FreeBSD 11.4, lib/libc/stdio/vfprintf.c:

	saved_errno = errno;
	...
		case 'm':
			cp = strerror(saved_errno);
			size = (prec >= 0) ? strnlen(cp, prec) : strlen(cp);
			sign = '\0';
			break;

The guest formatter now saves errno when it starts and formats %m as a
string with the guest strerror_r text, so width, precision and the -
flag apply as FreeBSD's string path applies them. On Linux a format with
%m goes to the guest formatter like one with a wide argument.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 03:12:27 +00:00
Dean d2d4c07aab Merge pull request #3978 from zmeizy/claude/asprintf-guest-wide
fix(libc): format 16-bit wide arguments in asprintf on Linux
2026-10-12 16:11:47 +13:00
Claude c35d05395d fix(libc): reject 16-bit wide conversions in sscanf_s and after the ' flag on Linux
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
2026-10-11 23:37:17 +00:00
Adrià 752db7da76 Merge pull request #3569 from DariusHQ/fix/libc-format-positional-arguments
fix(libc): format positional arguments on Windows
2026-10-11 23:40:52 +02:00
Adrià 41f013f664 Merge pull request #3567 from DariusHQ/fix/libc-format-grouping-flag
fix(libc): accept the ' flag in Windows formatting
2026-10-11 23:34:57 +02:00
Claude d358374ac8 fix(libc): throw for 16-bit wide scanf conversions on Linux
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
2026-10-11 20:07:20 +00:00
Claude 6b72296ef5 fix(libc): format 16-bit wide arguments in asprintf on Linux
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
2026-10-11 20:02:20 +00:00
DariusHQ b9fc448343 fix(libc): format positional arguments on Windows
The guest formatter threw on %n$ and *m$, which FreeBSD's vfprintf and
glibc accept. It now reads the arguments a numbered format names into a
table first, with the types their conversions give them, and follows
FreeBSD's rules for unnumbered conversions and unnamed arguments.
2026-10-11 16:19:13 +03:00
DariusHQ d9fe7ee614 fix(libc): accept the ' flag in Windows formatting
FreeBSD's vfprintf takes ' as the thousands-grouping flag. The Windows
formatter threw on it as an unsupported conversion. The guest's setlocale
only accepts the C locale, which has no thousands separator, so the flag
changes nothing: it is dropped before the host's printf sees it, and the
host's locale cannot add separators.
2026-10-11 16:19:12 +03:00
DariusHQ b1fe54e331 fix(libc): print 0 for %#.0o of zero on Windows
C and FreeBSD's vfprintf print a single 0 when # meets octal zero with a
precision of 0. The Windows formatter passed the conversion to the host's
printf, which printed nothing; it now asks for one digit instead.
2026-10-11 16:19:12 +03:00
Hussein Kadhim 09921dd376 fix(libc): return 0 from scanf when input fails after a suppressed conversion on Windows
C17 7.21.6.2p16 returns EOF only if input fails before the first conversion completes, and a suppressed conversion completes. FreeBSD counts it in nconversions (vfscanf.c, releng/11.4, lines 799-805). The host scanf returned EOF there, so sscanf("12", "%*d%d", &v) reported EOF instead of 0. Each suppressed conversion now records its end with a %n and a result of EOF becomes 0 when one was recorded.
2026-10-11 12:12:48 +02:00
Hussein Kadhim 44f00e2be8 fix(libc): format %p as FreeBSD does on Windows
The Windows formatter passed %p to the host CRT, which prints 16
zero-padded digits without a prefix. FreeBSD prints 0x followed by the
lowercase hex digits (0x0 for a null pointer), as if by %#lx.
2026-10-11 10:43:41 +02:00
MarcZX100 4d537755e9 test(libc): cover vsscanf_s capacity limits 2026-10-10 23:52:11 +02:00