Commit Graph
86 Commits
Author SHA1 Message Date
JJenkx e471b2e3a3 fix(libc): encode scanned extended NaNs in the guest format 2026-11-06 13:55:17 +01:00
JJenkxandClaude Opus 5.5 01a14b8964 fix(libc): store a scanned NaN as the default quiet NaN in sscanf_s
The libc.prx that titles ship (PPSA05916, PPSA07923) stores every NaN a
floating conversion reads as the positive default quiet NaN, whatever
its sign or payload: -nan gives 0x7fc00000 for %f, 0x7ff8000000000000
for %lf and 0x7fff:c000000000000000 for %Lf. The host scanners keep the
sign. The sscanf_s scanner now rewrites a stored NaN, ten bytes for %Lf.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 13:55:16 +01:00
Adrià f0f52cae5c Merge pull request #12530 from JJenkx/windows/libc-scanf-s-hex-prefix
fix(libc): fail a 0x with no hex digit and keep errno for in-range floats in sscanf_s
2026-11-06 13:25:58 +01:00
JJenkx 51f8ea279c merge: refresh libc formatting fix against current main 2026-11-05 15:21:21 -05:00
JJenkx aa8c1b58be chore(libc): retain scan conversion checks alongside input failures 2026-11-04 14:51:58 -05:00
JJenkx af0443d371 chore(libc): retain scan conversion checks alongside input failures 2026-11-04 14:51:57 -05:00
Dean 269419694c Merge pull request #13119 from JJenkx/fix/libc-ordinary-short-character-fields
fix(libc): retain ordinary short character scan fields
2026-11-05 08:19:45 +13:00
JJenkx 9083fe9a7e fix(libc): retain ordinary short character scan fields 2026-11-02 12:50:40 -05:00
JJenkx 4816b33918 fix(libc): print %C, %S and a zero %lc in the printf families as titles' libc.prx does 2026-11-02 12:44:56 -05:00
JJenkx 8cac89f55a fix(libc): print unknown printf conversions and ' as titles' libc.prx does 2026-11-02 12:44:56 -05:00
Dean Galvin b91bbc69d6 Merge commit '4f64f81ef7b4bca975b4b9f3dfd15dfff56f716f' into HEAD
# Conflicts:
#	core/libs/prx/libc/src/Formatting.cpp
2026-11-03 02:42:48 +13:00
JJenkxandClaude Opus 5.5 845f01e7de test(libc): pin that %C ends a narrow scan without reading input or later directives
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 18:52:28 -04:00
JJenkxandClaude Opus 5.5 145756d237 fix(libc): read %l[ scanset ranges as titles' libc.prx does
The narrow sscanf of titles' libc.prx (PPSA07923 and PPSA05916 agree)
reads a %l[ set left to right: X-Y is a byte range when a - follows a
member and is not last, a reversed range matches nothing, and a - first,
last or after a range is a member. InWideScanset made a reversed range's
first end a member and chained a following -, so %l[z-a] took z and
%l[a-a-c] took b. It now follows the rule swscanf's InSet uses.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 18:52:28 -04:00
JJenkxandClaude Opus 5.5 702ace9811 fix(libc): read wide scanf fields byte by byte, as titles' libc.prx does
Titles' libc.prx (PPSA07923, PPSA05916, PPSA13934) reads %ls, %lc, %l[
and %S by passing each byte to mbrtowc with the state kept for the
field, so in the C locale any byte from 0x80 up ends the conversion:

- a UTF-8 lead byte is held, and the next byte the field takes fails it
  with EILSEQ as a matching failure;
- a field that ends while a byte is held is an input failure;
- any other byte mbrtowc refuses is an input failure as the field's
  first byte and a matching failure after it;
- the units read before a failure stay stored without a terminator.

Widths count bytes, scanset members are compared as bytes, and %C is
not a conversion there, so it ends the scan.

The guest scanner decoded UTF-8 instead and threw for anything else, and
Windows handed these conversions to the host, which stored each byte as
one unit and threw for %S and %C. The scanner now does the above on every
platform, and Windows sends formats with a wide conversion to it, as
Linux does. Wide detection now follows the scanner's own rule, so %hS and
%lS count. The wide tests run on Windows too and expect the titles'
results; the UTF-8 cases they had are replaced by measured ones.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 18:52:13 -04:00
Adrià 91cd8ac6fd Merge pull request #13049 from JJenkx/fix/libc-character-scan-lengths
fix(libc): ignore non-wide lengths on character scans
2026-10-30 16:25:56 +01:00
JJenkx ce32d855ba fix(libc): ignore non-wide lengths on character scans 2026-10-29 19:33:32 -04:00
JJenkx 8a7cd7d35a fix(libc): preserve errno on string scan input exhaustion 2026-10-29 17:20:46 -04:00
JJenkx efdeef66aa merge: retain measured scanner debt and current-main quad behavior 2026-10-29 09:13:48 -04:00
Adrià 157b02c4f1 Merge pull request #11852 from ionut27001/fix/wf-scanf-q-length-linux
fix(libc): end sscanf and vsscanf at a q length on Linux and macOS
2026-10-29 13:57:18 +01:00
JJenkx 7240f69ca7 fix(libc): end unknown secure scans before checking input EOF 2026-10-29 01:19:10 -04:00
JJenkx 576b9e2441 fix(libc): stop incomplete Windows scan directives without changing errno 2026-10-29 01:12:12 -04:00
JJenkx b21ac041e7 fix(libc): bound scan length modifiers consistently 2026-10-29 01:07:31 -04:00
JJenkxandClaude Opus 5.5 3eca2be067 fix(libc): fail a 0x with no hex digit and keep errno for in-range floats in sscanf_s
The libc.prx that titles ship (PPSA05916, PPSA07923) does not take a
0x prefix with no hex digit after it as 0. A %x, %X, %i or %p field
fails as an input failure when the input or width ends after the x
and no sign precedes it, and as a matching failure otherwise; a
floating field needs a hex digit, or a dot and a hex digit. Floating
fields set ERANGE only when a decimal field is out of long double
range, so %e of 1e40 and %a of 0x1p200 leave errno alone.

sscanf_s and vsscanf_s now check the prefix before handing the field
to the host scanner and decide errno from the scanned text. The
stream forms cannot look three characters ahead and are unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-28 13:51:46 -04:00
JJenkxandClaude Opus 5.5 0b3eb0b3e5 fix(libc): wrap narrow integers in sscanf_s as titles' libc.prx does
The sscanf_s of titles' libc.prx (PPSA07923 and PPSA05916 agree) reads a
%d, %i, %o, %u, %x or %X with no length, h or hh as a 64-bit value and
keeps its low bits: %x of 61439ebdf stores 0x1439ebdf and leaves errno
alone. ScanSource handed the directive to the host at the destination's
width, which saturated to 0xffffffff and set ERANGE. It now scans those
conversions into a 64-bit temporary and stores the low bytes, as the
plain Windows sscanf path already does. Out of 64-bit range the host
still saturates with ERANGE, as the titles do.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-28 12:21:23 -04:00
JJenkxandClaude Opus 5.5 7ca098105a fix(libc): read narrow scansets, string lengths and unknown conversions as titles do on Windows
The narrow sscanf and sscanf_s of titles' libc.prx (PPSA07923 and
PPSA05916 agree) differ from the host scanner Windows used:

- scanset ranges are read left to right: X-Y is a range when a - follows
  a member and is not last, a reversed range matches nothing, a - first,
  last or after a range is a member, and a ] that opens the set can
  start a range; an unterminated set ends the scan as a matching failure;
- %s, %c and %[ read narrow with any length but l, where the host read
  %lls as wide;
- an unknown conversion such as %y is a matching failure, even at the
  end of the input, where it threw or returned EOF.

Scansets are now rewritten as explicit byte lists, so the host's range
rules never apply, the length of s, c and [ is dropped unless it is l,
and an unknown conversion ends the scan.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-28 09:16:43 -04:00
ionut27001 6135c0e3a0 fix(libc): limit the q-length cut to sscanf and vsscanf 2026-10-27 14:23:42 +02:00
JJenkxandClaude Opus 5.5 17c950f0a5 test(libc): pass argument types that match ignored printf lengths
%Ld formats an int once L is ignored, so the test passes a negative int
instead of an unsigned value, and %Ln writes an int, so the test counts
into an int followed by a guard instead of reading a long long.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-27 08:18:07 -04:00
JJenkxandClaude Opus 5.5 4630a53d0e fix(libc): ignore printf length modifiers that do not apply, as titles' libc.prx does
The printf family threw for a length modifier its conversion does not
take, such as %Ld, %hhc, %Ls, %hf or %hp, and the wide family returned
-1. The libc.prx bundled with titles ignores such a modifier: L on an
integer conversion or %n (an int), any length but l on %c and %s, any
but L on a floating conversion, and any on %p. Both formatters now drop
it before converting, and on Linux such a format goes to the guest
formatter. The _s forms, unmeasured, still throw.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-27 07:50:36 -04:00
ionut27001 ead2b0ed1a fix(libc): end the scan at a q length on Linux and macOS 2026-10-27 11:24:20 +02:00
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