Paul Eggert wrote:
> The problem is that ("%*d", INT_MAX, n) fails because the code
> refuses to create a buffer of size INT_MAX + 1u,
> due to problems when dealing with older nonconforming snprintf.

Thanks for working on this.

The change introduces a compilation error on MSVC:
D:\a\ci-testdir-check\ci-testdir-check\testdir-all\gllib\vasnprintf.c(231): 
fatal error C1017: invalid integer constant expression

The cause is that you assumed that the various platform-specific
macros expand to non-zero numbers. Which is not the case.

This patch fixes it. Also, for maintainability, don't declare multiple
variables in a single declaration.


2026-07-13  Bruno Haible  <[email protected]>

        vasnprintf: Fix compilation error on MSVC (regression 2026-07-06).
        * lib/vasnprintf.c (USE_SNPRINTF): Fix condition.
        (VASNPRINTF): Avoid declaring multiple variables in one declaration.

diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c
index 98d8e4a757..60d3c8bda1 100644
--- a/lib/vasnprintf.c
+++ b/lib/vasnprintf.c
@@ -219,16 +219,19 @@
   /* TCHAR_T is char.  */
   /* Use snprintf if it exists under the name 'snprintf' or '_snprintf'.
      But don't use it if it has problems.  For example,
-     Solaris, QNX and z/OS sprintf fail if size == INT_MAX + 1u,
-     BeOS produces no output if 0x3000000 <= size,
-     and Linux libc5 with size = 1 writes without bounds, like sprintf.
+     Solaris, QNX and z/OS snprintf fail if size == INT_MAX + 1u,
+     BeOS snprintf produces no output if size >= 0x3000000,
+     and Linux libc5 with size == 1 writes without bounds, like sprintf.
      BSD snprintf, which fails if size == INT_MAX + 2u, is OK for us.
      Use snprintf only on known-safe platforms:
-     glibc 2, Android, musl, the BSDs, macOS, Microsoft UCRT.  */
+     glibc 2, musl libc, macOS, FreeBSD, NetBSD, OpenBSD, Android,
+     Microsoft UCRT.  */
 # if ((HAVE_SNPRINTF || HAVE_DECL__SNPRINTF) \
-      && (2 <= __GLIBC__ || __ANDROID__ || MUSL_LIBC \
-          || __FreeBSD__ || __DragonFly__ || __NetBSD__ || __OpenBSD__ \
-          || (__APPLE__ && __MACH__) || _UCRT))
+      && (2 <= __GLIBC__ || MUSL_LIBC \
+          || (defined __APPLE__ && defined __MACH__) \
+          || (defined __FreeBSD__ || defined __DragonFly__) \
+          || defined __NetBSD__ || defined __OpenBSD__ \
+          || defined __ANDROID__ || defined _UCRT))
 #  define USE_SNPRINTF 1
 # else
 #  define USE_SNPRINTF 0
@@ -6868,17 +6871,16 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
 
                     /* Keep size (in bytes) in ptrdiff_t and size_t range.
                        Also, generate at most INT_MAX + 1 characters
-                       counting the trailing null, as that is the
+                       counting the trailing NUL, as that is the
                        maximum the API allows.  */
-                    size_t
-                      bytes_max = MIN (PTRDIFF_MAX, SIZE_MAX),
-                      tchars_max = bytes_max / sizeof (TCHAR_T),
-                      API_max = MIN (tchars_max - 1, INT_MAX),
-                      maxlen_max = (API_max + 1
-                                    - (API_max + 1) % TCHARS_PER_DCHAR),
-                      maxlen = (MIN (allocated - length,
-                                     maxlen_max / TCHARS_PER_DCHAR)
-                                * TCHARS_PER_DCHAR);
+                    size_t bytes_max = MIN (PTRDIFF_MAX, SIZE_MAX);
+                    size_t tchars_max = bytes_max / sizeof (TCHAR_T);
+                    size_t API_max = MIN (tchars_max - 1, INT_MAX);
+                    size_t maxlen_max =
+                      (API_max + 1) - (API_max + 1) % TCHARS_PER_DCHAR;
+                    size_t maxlen =
+                      MIN (allocated - length, maxlen_max / TCHARS_PER_DCHAR)
+                      * TCHARS_PER_DCHAR;
 # define SNPRINTF_BUF(arg) \
                     switch (prefix_count)                                   \
                       {                                                     \




Reply via email to