unistdio/ulc-*printf: Fix padding on 32-bit Cygwin

Bruno Haible via Gnulib discussion list <[email protected]>
Newsgroups gmane.comp.lib.gnulib.bugs
Message-ID <3308930.aKNjEaI27c@cagnes>
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;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.