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;




Reply via email to