From a034cceacdbe77694853524abce487a06937b016 Mon Sep 17 00:00:00 2001 From: JJenkx Date: Thu, 22 Oct 2026 20:06:33 -0400 Subject: [PATCH] fix(libc): ignore the space and plus flags on wide unsigned conversions The wide printf family passed its flags to the host for %o, %u, %x and %X, and the UCRT honours a space flag on %u, so swprintf "% u" of 7 gave " 7". The libc.prx that titles ship applies the space and plus flags to signed conversions only and gives "7". Drop them before the host formats an unsigned conversion. Co-Authored-By: Claude Opus 5.5 --- core/libs/prx/libc/src/FormattingWide.cpp | 3 +++ core/libs/tests/GuestWideFormatting.cpp | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/core/libs/prx/libc/src/FormattingWide.cpp b/core/libs/prx/libc/src/FormattingWide.cpp index a2b3d0fe7d..9f6dba530c 100644 --- a/core/libs/prx/libc/src/FormattingWide.cpp +++ b/core/libs/prx/libc/src/FormattingWide.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -169,6 +170,8 @@ std::u16string FormatWide(const char16_t* format, VaList* source, bool secure = } else value = args.Next(); if (conversion == u'o' && value == 0 && precision == 0 && spec.find('#') != std::string::npos) spec = spec.substr(0, spec.find('.')) + ".1"; + const auto flags = spec.begin() + static_cast(std::min(spec.find_first_not_of("-+ #0", 1), spec.size())); + spec.erase(std::remove_if(spec.begin() + 1, flags, [](char flag) { return flag == ' ' || flag == '+'; }), flags); AppendNumber(out, spec + "ll" + static_cast(conversion), value); } else if (In(conversion, "aAeEfFgG")) { if (length == "L") AppendNumber(out, spec + "L" + static_cast(conversion), args.Next()); diff --git a/core/libs/tests/GuestWideFormatting.cpp b/core/libs/tests/GuestWideFormatting.cpp index 8ebfa2753e..7a1552e9c7 100644 --- a/core/libs/tests/GuestWideFormatting.cpp +++ b/core/libs/tests/GuestWideFormatting.cpp @@ -146,6 +146,12 @@ static void CheckCount() { Require(Format(buffer, 16, u"a%n", nullCount) < 0, "vswprintf null %n argument"); } +static void CheckUnsignedSignFlags() { + char16_t buffer[32]; + Require(swprintf_nid_postfix(buffer, 32, u"[% u|%+u|% lu|% 5u|%+x|% #o]", 7u, 7u, 7ul, 7u, 7u, 7u) == 18 && + buffer == std::u16string(u"[7|7|7| 7|7|07]"), "unsigned conversions ignore the space and plus flags"); +} + static void CheckGroupingFlag() { char16_t buffer[48]; Require(swprintf_nid_postfix(buffer, 48, u"%'d|%'-6u|%'.2f|%'+05d|%'g", 1234567, 42u, 1234.5, 12, 1e6) == 34 && @@ -322,4 +328,5 @@ int main() { Check(u"%.1s", "\xf0\x9f\x98\x80x", u""); Check(u"%.3s", "\xf0\x9f\x98\x80x", u"\U0001f600x"); CheckGroupingFlag(); + CheckUnsignedSignFlags(); }