The libunistring CI reports a test failure on 32-bit Cygwin:
FAIL: unistdio/test-ulc-vasnprintf3.sh ====================================== ../../gltests/unistdio/test-ulc-vasnprintf3.c:222: assertion 'streq (result, "\303\204rger 33")' failed ../../gltests/unistdio/test-ulc-vasnprintf3.c:231: assertion 'streq (result, " \303\204rger 33")' failed FAIL unistdio/test-ulc-vasnprintf3.sh (exit status: 1) Regarding the first test case, basically ulc_vasnsprintf (..., "%-10s %d", "Ärger", 33, 44, 55); the expected result being "Ärger 33", the actual result is "Ärger 33" (one space less). The cause is that a wrong pointer gets passed to the mbsnlen() function, resulting in mbsnlen() returning 6 instead of 5. This happens as a consequence of the 2026-07-06 change: Before, USE_SNPRINTF was 1 on Cygwin; now it is 0. It does not happen on 64-bit Cygwin, because there the processing of the %s directive starts at lib/vasnprintf.c line 3060 — a different code path. This patch fixes it. 2026-08-15 Bruno Haible <[email protected]> unistdio/ulc-*printf: Fix padding on 32-bit Cygwin (regr. 2026-07-06). * lib/vasnprintf.c (VASNPRINTF): In the 32-bit handling of the %s directive, if DCHAR_IS_TCHAR && !USE_SNPRINTF, pass the correct address to mbsnlen(). diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c index 10e6af5bf9..c265a8bbe4 100644 --- a/lib/vasnprintf.c +++ b/lib/vasnprintf.c @@ -7646,33 +7646,41 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, if (pad_ourselves && has_width) { size_t w; + { +# if !DCHAR_IS_TCHAR || USE_SNPRINTF + DCHAR_T * const rp = result + length; +# else + DCHAR_T * const rp = tmp; +# endif # if ENABLE_UNISTDIO - /* Outside POSIX, it's preferable to compare the width - against the number of _characters_ of the converted - value. */ - w = DCHAR_MBSNLEN (result + length, count); + /* Outside POSIX, it's preferable to compare the width + against the number of _characters_ of the converted + value. */ + w = DCHAR_MBSNLEN (rp, count); # elif __GLIBC__ >= 2 - /* glibc prefers to compare the width against the number - of characters as well, but only for numeric conversion - specifiers. See - <https://sourceware.org/PR28943> - <https://sourceware.org/PR30883> - <https://sourceware.org/PR31542> */ - switch (dp->conversion) - { - case 'd': case 'i': case 'u': - case 'f': case 'F': case 'g': case 'G': - w = DCHAR_MBSNLEN (result + length, count); - break; - default: - w = count; - break; - } + /* glibc prefers to compare the width against the + number of characters as well, but only for numeric + conversion specifiers. See + <https://sourceware.org/PR28943> + <https://sourceware.org/PR30883> + <https://sourceware.org/PR31542> */ + switch (dp->conversion) + { + case 'd': case 'i': case 'u': + case 'f': case 'F': case 'g': case 'G': + w = DCHAR_MBSNLEN (rp, count); + break; + default: + w = count; + break; + } # else - /* The width is compared against the number of _bytes_ - of the converted value, says POSIX. */ - w = count; + /* The width is compared against the number of _bytes_ + of the converted value, says POSIX. */ + (void) rp; + w = count; # endif + } if (w < width) { size_t pad = width - w;
