I'm still working on allowing *printf results of size > 2 GiB.

One of the issues here is what to do when a width > INT_MAX
is specified directly in the format string, for example
"%03000000000d".

ISO C ยง 7.23.6.1 only says that this should be a "nonnegative decimal integer",
but doesn't give a limit.

I think it is useful to limit the width to the range 0..INT_MAX, because

  * That's what most platforms (all I tested, except AIX and mingw) do:
    if the width is > INT_MAX, the snprintf call fails (with EOVERFLOW
    on most platforms, and with ERANGE on MSVC.) See the attached test
    program.

  * It's consistent with passing the width as an 'int' argument: "%*d".
    It would be odd if an application could use the 'int' argument for some
    widths and had to use a dynamically created format string for larger
    widths.


2024-06-14  Bruno Haible  <br...@clisp.org>

        vasnprintf: Reject a width > INT_MAX.
        * lib/vasnprintf.c (VASNPRINTF): If a width is > INT_MAX, fail with
        EOVERFLOW.
        * tests/test-vasnprintf.c: Include <errno.h>.
        (test_function): Test huge widths.
        * tests/test-vasnwprintf.c: Include <errno.h>.
        (test_function): Test huge widths.
        * tests/unistdio/test-u8-asnprintf1.h (test_function): Test huge widths.
        * tests/unistdio/test-u16-asnprintf1.h (test_function): Likewise.
        * tests/unistdio/test-u32-asnprintf1.h (test_function): Likewise.
        * tests/unistdio/test-ulc-asnprintf1.h (test_function): Likewise.
        * tests/unistdio/test-ulc-asnprintf1.c: Include <errno.h>.
        * tests/unistdio/test-ulc-vasnprintf1.c: Likewise.

diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c
index 03a7da71f9..0242dd3f55 100644
--- a/lib/vasnprintf.c
+++ b/lib/vasnprintf.c
@@ -85,7 +85,7 @@
 #include <string.h>     /* memcpy(), strlen() */
 #include <wchar.h>      /* mbstate_t, mbrtowc(), mbrlen(), wcrtomb(), 
mbszero() */
 #include <errno.h>      /* errno */
-#include <limits.h>     /* CHAR_BIT, INT_WIDTH, LONG_WIDTH */
+#include <limits.h>     /* CHAR_BIT, INT_MAX, INT_WIDTH, LONG_WIDTH */
 #include <float.h>      /* DBL_MAX_EXP, LDBL_MAX_EXP, LDBL_MANT_DIG */
 #if HAVE_NL_LANGINFO
 # include <langinfo.h>
@@ -2458,6 +2458,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                           width = xsum (xtimes (width, 10), *digitp++ - '0');
                         while (digitp != dp->width_end);
                       }
+                    if (width > (size_t) INT_MAX)
+                      goto overflow;
                     has_width = 1;
                   }
 
@@ -2845,6 +2847,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                           width = xsum (xtimes (width, 10), *digitp++ - '0');
                         while (digitp != dp->width_end);
                       }
+                    if (width > (size_t) INT_MAX)
+                      goto overflow;
                   }
 
                 {
@@ -3000,6 +3004,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                           width = xsum (xtimes (width, 10), *digitp++ - '0');
                         while (digitp != dp->width_end);
                       }
+                    if (width > (size_t) INT_MAX)
+                      goto overflow;
                     has_width = 1;
                   }
 
@@ -3441,6 +3447,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                           width = xsum (xtimes (width, 10), *digitp++ - '0');
                         while (digitp != dp->width_end);
                       }
+                    if (width > (size_t) INT_MAX)
+                      goto overflow;
                     has_width = 1;
                   }
 
@@ -3629,6 +3637,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                           width = xsum (xtimes (width, 10), *digitp++ - '0');
                         while (digitp != dp->width_end);
                       }
+                    if (width > (size_t) INT_MAX)
+                      goto overflow;
                   }
 
                 /* %c in vasnwprintf.  See the specification of fwprintf.  */
@@ -3717,6 +3727,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                           width = xsum (xtimes (width, 10), *digitp++ - '0');
                         while (digitp != dp->width_end);
                       }
+                    if (width > (size_t) INT_MAX)
+                      goto overflow;
                     has_width = 1;
                   }
 
@@ -4031,6 +4043,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                           width = xsum (xtimes (width, 10), *digitp++ - '0');
                         while (digitp != dp->width_end);
                       }
+                    if (width > (size_t) INT_MAX)
+                      goto overflow;
                   }
 
                 has_precision = 0;
@@ -4536,6 +4550,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                           width = xsum (xtimes (width, 10), *digitp++ - '0');
                         while (digitp != dp->width_end);
                       }
+                    if (width > (size_t) INT_MAX)
+                      goto overflow;
                   }
 
                 has_precision = 0;
@@ -5718,6 +5734,9 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                           width = xsum (xtimes (width, 10), *digitp++ - '0');
                         while (digitp != dp->width_end);
                       }
+                    if (width > (size_t) INT_MAX)
+                      goto overflow;
+# define WIDTH_IS_CHECKED 1
 # if (WIDE_CHAR_VERSION && MUSL_LIBC) || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || 
NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || 
NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
                     has_width = 1;
 # endif
@@ -5867,6 +5886,43 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                     if (dp->width_start != dp->width_end)
                       {
                         size_t n = dp->width_end - dp->width_start;
+#if !WIDTH_IS_CHECKED
+                        size_t width;
+                        /* Reject an out-of-range width.
+                           The underlying SNPRINTF already does this on some
+                           platforms (glibc, musl, macOS, FreeBSD, NetBSD,
+                           OpenBSD, Cygwin, Solaris, MSVC).  However, on others
+                           (AIX, mingw), it doesn't; thus this vasnprintf
+                           invocation would succeed and produce a wrong result.
+                           So, this is redundant on some platforms, but it's a
+                           quick check anyway.  */
+                        if (dp->width_arg_index != ARG_NONE)
+                          {
+                            int arg;
+
+                            if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+                              abort ();
+                            arg = a.arg[dp->width_arg_index].a.a_int;
+                            width = arg;
+                            if (arg < 0)
+                              {
+                                /* "A negative field width is taken as a '-' 
flag
+                                    followed by a positive field width."  */
+                                width = -width;
+                              }
+                          }
+                        else
+                          {
+                            const FCHAR_T *digitp = dp->width_start;
+
+                            width = 0;
+                            do
+                              width = xsum (xtimes (width, 10), *digitp++ - 
'0');
+                            while (digitp != dp->width_end);
+                          }
+                        if (width > (size_t) INT_MAX)
+                          goto overflow;
+#endif
                         /* The width specification is known to consist only
                            of standard ASCII characters.  */
                         if (sizeof (FCHAR_T) == sizeof (TCHAR_T))
@@ -6960,11 +7016,9 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
        not have this limitation.  */
     return result;
 
-#if USE_SNPRINTF
   overflow:
     errno = EOVERFLOW;
     goto fail_with_errno;
-#endif
 
   out_of_memory:
     errno = ENOMEM;
diff --git a/tests/test-vasnprintf.c b/tests/test-vasnprintf.c
index 655603f7e1..d6182dc461 100644
--- a/tests/test-vasnprintf.c
+++ b/tests/test-vasnprintf.c
@@ -20,6 +20,7 @@
 
 #include "vasnprintf.h"
 
+#include <errno.h>
 #include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
@@ -86,6 +87,58 @@ test_function (char * (*my_asnprintf) (char *, size_t *, 
const char *, ...))
       if (result != buf)
         free (result);
     }
+
+  /* Verify that [v]asnprintf() rejects a width > 2 GiB, < 4 GiB.  */
+  {
+    size_t length;
+    char *s = my_asnprintf (NULL, &length, "x%03000000000dy\n", -17);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+  {
+    size_t length;
+    char *s = my_asnprintf (NULL, &length, "x%03000000000cy\n", '@');
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+
+  /* Verify that [v]asnprintf() rejects a width > 4 GiB.  */
+  {
+    size_t length;
+    char *s =
+      my_asnprintf (NULL, &length,
+                    "x%04294967306dy\n", /* 2^32 + 10 */
+                    -17);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+  {
+    size_t length;
+    char *s =
+      my_asnprintf (NULL, &length,
+                    "x%04294967306cy\n", /* 2^32 + 10 */
+                    '@');
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+  {
+    size_t length;
+    char *s =
+      my_asnprintf (NULL, &length,
+                    "x%018446744073709551626dy\n", /* 2^64 + 10 */
+                    -17);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+  {
+    size_t length;
+    char *s =
+      my_asnprintf (NULL, &length,
+                    "x%018446744073709551626cy\n", /* 2^64 + 10 */
+                    '@');
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
 }
 
 static char *
diff --git a/tests/test-vasnwprintf.c b/tests/test-vasnwprintf.c
index 5d6034045e..a5832a9080 100644
--- a/tests/test-vasnwprintf.c
+++ b/tests/test-vasnwprintf.c
@@ -20,6 +20,7 @@
 
 #include "vasnwprintf.h"
 
+#include <errno.h>
 #include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
@@ -87,6 +88,58 @@ test_function (wchar_t * (*my_asnwprintf) (wchar_t *, size_t 
*, const wchar_t *,
       if (result != buf)
         free (result);
     }
+
+  /* Verify that [v]asnwprintf() rejects a width > 2 GiB, < 4 GiB.  */
+  {
+    size_t length;
+    wchar_t *s = my_asnwprintf (NULL, &length, L"x%03000000000dy\n", -17);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+  {
+    size_t length;
+    wchar_t *s = my_asnwprintf (NULL, &length, L"x%03000000000cy\n", '@');
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+
+  /* Verify that [v]asnwprintf() rejects a width > 4 GiB.  */
+  {
+    size_t length;
+    wchar_t *s =
+      my_asnwprintf (NULL, &length,
+                     L"x%04294967306dy\n", /* 2^32 + 10 */
+                     -17);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+  {
+    size_t length;
+    wchar_t *s =
+      my_asnwprintf (NULL, &length,
+                     L"x%04294967306cy\n", /* 2^32 + 10 */
+                     '@');
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+  {
+    size_t length;
+    wchar_t *s =
+      my_asnwprintf (NULL, &length,
+                     L"x%018446744073709551626dy\n", /* 2^64 + 10 */
+                     -17);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+  {
+    size_t length;
+    wchar_t *s =
+      my_asnwprintf (NULL, &length,
+                     L"x%018446744073709551626cy\n", /* 2^64 + 10 */
+                     '@');
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
 }
 
 static wchar_t *
diff --git a/tests/unistdio/test-u16-asnprintf1.h 
b/tests/unistdio/test-u16-asnprintf1.h
index 4ec31a431c..2b1a9ab317 100644
--- a/tests/unistdio/test-u16-asnprintf1.h
+++ b/tests/unistdio/test-u16-asnprintf1.h
@@ -57,4 +57,59 @@ test_function (uint16_t * (*my_asnprintf) (uint16_t *, 
size_t *, const char *, .
       if (result != buf)
         free (result);
     }
+
+  /* Verify that u16_[v]asnprintf() rejects a width > 2 GiB, < 4 GiB.  */
+  {
+    size_t length;
+    uint16_t *s = my_asnprintf (NULL, &length, "x%03000000000dy\n", -17);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+  {
+    static const uint16_t arg[] = { '@', 0 };
+    size_t length;
+    uint16_t *s = my_asnprintf (NULL, &length, "x%03000000000lUy\n", arg);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+
+  /* Verify that u16_[v]asnprintf() rejects a width > 4 GiB.  */
+  {
+    size_t length;
+    uint16_t *s =
+      my_asnprintf (NULL, &length,
+                    "x%04294967306dy\n", /* 2^32 + 10 */
+                    -17);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+  {
+    static const uint16_t arg[] = { '@', 0 };
+    size_t length;
+    uint16_t *s =
+      my_asnprintf (NULL, &length,
+                    "x%04294967306lUy\n", /* 2^32 + 10 */
+                    arg);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+  {
+    size_t length;
+    uint16_t *s =
+      my_asnprintf (NULL, &length,
+                    "x%018446744073709551626dy\n", /* 2^64 + 10 */
+                    -17);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+  {
+    static const uint16_t arg[] = { '@', 0 };
+    size_t length;
+    uint16_t *s =
+      my_asnprintf (NULL, &length,
+                    "x%018446744073709551626lUy\n", /* 2^64 + 10 */
+                    arg);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
 }
diff --git a/tests/unistdio/test-u32-asnprintf1.h 
b/tests/unistdio/test-u32-asnprintf1.h
index 85fa2cf078..af78684891 100644
--- a/tests/unistdio/test-u32-asnprintf1.h
+++ b/tests/unistdio/test-u32-asnprintf1.h
@@ -57,4 +57,59 @@ test_function (uint32_t * (*my_asnprintf) (uint32_t *, 
size_t *, const char *, .
       if (result != buf)
         free (result);
     }
+
+  /* Verify that u32_[v]asnprintf() rejects a width > 2 GiB, < 4 GiB.  */
+  {
+    size_t length;
+    uint32_t *s = my_asnprintf (NULL, &length, "x%03000000000dy\n", -17);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+  {
+    static const uint32_t arg[] = { '@', 0 };
+    size_t length;
+    uint32_t *s = my_asnprintf (NULL, &length, "x%03000000000llUy\n", arg);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+
+  /* Verify that u32_[v]asnprintf() rejects a width > 4 GiB.  */
+  {
+    size_t length;
+    uint32_t *s =
+      my_asnprintf (NULL, &length,
+                    "x%04294967306dy\n", /* 2^32 + 10 */
+                    -17);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+  {
+    static const uint32_t arg[] = { '@', 0 };
+    size_t length;
+    uint32_t *s =
+      my_asnprintf (NULL, &length,
+                    "x%04294967306llUy\n", /* 2^32 + 10 */
+                    arg);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+  {
+    size_t length;
+    uint32_t *s =
+      my_asnprintf (NULL, &length,
+                    "x%018446744073709551626dy\n", /* 2^64 + 10 */
+                    -17);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+  {
+    static const uint32_t arg[] = { '@', 0 };
+    size_t length;
+    uint32_t *s =
+      my_asnprintf (NULL, &length,
+                    "x%018446744073709551626llUy\n", /* 2^64 + 10 */
+                    arg);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
 }
diff --git a/tests/unistdio/test-u8-asnprintf1.h 
b/tests/unistdio/test-u8-asnprintf1.h
index f48e2365cb..7c2c3622f4 100644
--- a/tests/unistdio/test-u8-asnprintf1.h
+++ b/tests/unistdio/test-u8-asnprintf1.h
@@ -54,4 +54,59 @@ test_function (uint8_t * (*my_asnprintf) (uint8_t *, size_t 
*, const char *, ...
       if (result != buf)
         free (result);
     }
+
+  /* Verify that u8_[v]asnprintf() rejects a width > 2 GiB, < 4 GiB.  */
+  {
+    size_t length;
+    uint8_t *s = my_asnprintf (NULL, &length, "x%03000000000dy\n", -17);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+  {
+    static const uint8_t arg[] = { '@', 0 };
+    size_t length;
+    uint8_t *s = my_asnprintf (NULL, &length, "x%03000000000Uy\n", arg);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+
+  /* Verify that u8_[v]asnprintf() rejects a width > 4 GiB.  */
+  {
+    size_t length;
+    uint8_t *s =
+      my_asnprintf (NULL, &length,
+                    "x%04294967306dy\n", /* 2^32 + 10 */
+                    -17);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+  {
+    static const uint8_t arg[] = { '@', 0 };
+    size_t length;
+    uint8_t *s =
+      my_asnprintf (NULL, &length,
+                    "x%04294967306Uy\n", /* 2^32 + 10 */
+                    arg);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+  {
+    size_t length;
+    uint8_t *s =
+      my_asnprintf (NULL, &length,
+                    "x%018446744073709551626dy\n", /* 2^64 + 10 */
+                    -17);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+  {
+    static const uint8_t arg[] = { '@', 0 };
+    size_t length;
+    uint8_t *s =
+      my_asnprintf (NULL, &length,
+                    "x%018446744073709551626Uy\n", /* 2^64 + 10 */
+                    arg);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
 }
diff --git a/tests/unistdio/test-ulc-asnprintf1.c 
b/tests/unistdio/test-ulc-asnprintf1.c
index ced342e365..8fb91da026 100644
--- a/tests/unistdio/test-ulc-asnprintf1.c
+++ b/tests/unistdio/test-ulc-asnprintf1.c
@@ -20,6 +20,7 @@
 
 #include "unistdio.h"
 
+#include <errno.h>
 #include <stdarg.h>
 #include <stddef.h>
 #include <stdint.h>
diff --git a/tests/unistdio/test-ulc-asnprintf1.h 
b/tests/unistdio/test-ulc-asnprintf1.h
index 9e11f31465..8ede282f55 100644
--- a/tests/unistdio/test-ulc-asnprintf1.h
+++ b/tests/unistdio/test-ulc-asnprintf1.h
@@ -51,4 +51,59 @@ test_function (char * (*my_asnprintf) (char *, size_t *, 
const char *, ...))
       if (result != buf)
         free (result);
     }
+
+  /* Verify that ulc_[v]asnprintf() rejects a width > 2 GiB, < 4 GiB.  */
+  {
+    size_t length;
+    char *s = my_asnprintf (NULL, &length, "x%03000000000dy\n", -17);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+  {
+    static const uint8_t arg[] = { '@', 0 };
+    size_t length;
+    char *s = my_asnprintf (NULL, &length, "x%03000000000Uy\n", arg);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+
+  /* Verify that ulc_[v]asnprintf() rejects a width > 4 GiB.  */
+  {
+    size_t length;
+    char *s =
+      my_asnprintf (NULL, &length,
+                    "x%04294967306dy\n", /* 2^32 + 10 */
+                    -17);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+  {
+    static const uint8_t arg[] = { '@', 0 };
+    size_t length;
+    char *s =
+      my_asnprintf (NULL, &length,
+                    "x%04294967306Uy\n", /* 2^32 + 10 */
+                    arg);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+  {
+    size_t length;
+    char *s =
+      my_asnprintf (NULL, &length,
+                    "x%018446744073709551626dy\n", /* 2^64 + 10 */
+                    -17);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
+  {
+    static const uint8_t arg[] = { '@', 0 };
+    size_t length;
+    char *s =
+      my_asnprintf (NULL, &length,
+                    "x%018446744073709551626Uy\n", /* 2^64 + 10 */
+                    arg);
+    ASSERT (s == NULL);
+    ASSERT (errno == EOVERFLOW);
+  }
 }
diff --git a/tests/unistdio/test-ulc-vasnprintf1.c 
b/tests/unistdio/test-ulc-vasnprintf1.c
index 83557dbb4c..4352ff038b 100644
--- a/tests/unistdio/test-ulc-vasnprintf1.c
+++ b/tests/unistdio/test-ulc-vasnprintf1.c
@@ -20,6 +20,7 @@
 
 #include "unistdio.h"
 
+#include <errno.h>
 #include <stdarg.h>
 #include <stddef.h>
 #include <stdint.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#if !defined _WIN32
#include <sys/mman.h>
#endif

int main ()
{
  int ret;

  fprintf (stderr, "Doing output to stdout...\n"); fflush (stderr);
  ret = printf ("x%03000000000dy\n", -17);
  if (ret >= 0)
    fprintf (stderr, "  ... ret = %d\n", ret);
  else
    fprintf (stderr, "  ... ret = %d, errno=%s%s%s(%d)\n", ret, errno==ENOMEM?"ENOMEM":"", errno==EOVERFLOW?"EOVERFLOW":"", errno==ERANGE?"ERANGE":"", errno);

  fprintf (stderr, "Doing output to string...\n"); fflush (stderr);
  {
    char *buf = malloc (3000000100U);
#if !defined _WIN32
    if (buf == NULL)
      buf = mmap (NULL, 3000000512U, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
#endif
    if (buf == NULL)
      fprintf (stderr, "  ... malloc failed\n");
    else
      {
        int ret = snprintf (buf, 3000000100U, "x%03000000000dy\n", -17);
        if (ret >= 0)
          fprintf (stderr, "  ... ret = %d\n", ret);
        else
          fprintf (stderr, "  ... ret = %d, errno=%s%s%s(%d)\n", ret, errno==ENOMEM?"ENOMEM":"", errno==EOVERFLOW?"EOVERFLOW":"", errno==ERANGE?"ERANGE":"", errno);
      }
  }

  return 0;
}
/*
On 64-bit platforms, use: ./a.out >/dev/null

glibc, musl, macOS, OpenBSD (after allowing 10 GiB, through "ulimit -d 10485760"):
Doing output to stdout...
  ... ret = -1, errno=EOVERFLOW
Doing output to string...
  ... ret = -1, errno=EOVERFLOW

FreeBSD, NetBSD, Cygwin:
Doing output to stdout...
  ... ret = 6
Doing output to string...
  ... ret = -1, errno=EOVERFLOW

AIX:
Doing output to stdout...
  ... ret = 6
Doing output to string...
  ... ret = 0

Solaris 10,11:
Doing output to stdout...  (takes a while)
  ... ret = -1, errno=EOVERFLOW
Doing output to string...
  ... ret = -1, errno=EOVERFLOW

mingw:
Doing output to stdout...
  ... ret = 6
Doing output to string...
  ... ret = 6

MSVC:
Doing output to stdout...
  ... ret = -1, errno=ERANGE
Doing output to string...
  ... ret = -1, errno=ERANGE
*/

Reply via email to