Fix endless loop when the given allocated size was > INT_MAX.
authorBruno Haible <bruno@clisp.org>
Sun, 18 Mar 2007 00:31:50 +0000 (00:31 +0000)
committerBruno Haible <bruno@clisp.org>
Sun, 18 Mar 2007 00:31:50 +0000 (00:31 +0000)
ChangeLog
lib/sprintf.c
lib/vasnprintf.c
lib/vsprintf.c

index 42690fc..4e472c2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
 2007-03-17  Bruno Haible  <bruno@clisp.org>
 
+       Fix endless loop when the given allocated size was > INT_MAX.
+       * lib/vasnprintf.c (EOVERFLOW): New fallback definition.
+       (VASNPRINTF): Fail with EOVERFLOW when the given allocated size is
+       larger than INT_MAX, or when it grow to a value larger than INT_MAX.
+       * lib/vsprintf.c (vsprintf): Don't pass a size > INT_MAX to vasnprintf.
+       * lib/sprintf.c (sprintf): Likewise.
+
+2007-03-17  Bruno Haible  <bruno@clisp.org>
+
        * tests/test-argp-2.sh (func_compare): Output a context diff.
 
 2007-03-17  Bruno Haible  <bruno@clisp.org>
index ee71689..ab14107 100644 (file)
@@ -46,7 +46,9 @@ sprintf (char *str, const char *format, ...)
 {
   char *output;
   size_t len;
-  size_t lenbuf = SIZE_MAX;
+  /* vasnprintf fails with EOVERFLOW when the buffer size argument is larger
+     than INT_MAX (if that fits into a 'size_t' at all).  */
+  size_t lenbuf = (SIZE_MAX < INT_MAX ? SIZE_MAX : INT_MAX);
   va_list args;
 
   va_start (args, format);
index b13dbd5..8d0f516 100644 (file)
 # endif
 #endif
 
+/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW.  */
+#ifndef EOVERFLOW
+# define EOVERFLOW E2BIG
+#endif
+
 #if HAVE_WCHAR_T
 # if HAVE_WCSLEN
 #  define local_wcslen wcslen
@@ -179,6 +184,10 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
       {
        result = resultbuf;
        allocated = *lengthp;
+       /* POSIX says that snprintf() fails with EOVERFLOW when the specified
+          buffer size is larger than INT_MAX.  Let's do the same here.  */
+       if (allocated > INT_MAX)
+         goto overflow;
       }
     else
       {
@@ -1107,6 +1116,9 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
                    retcount = 0;
 
 #if USE_SNPRINTF
+                   /* SNPRINTF can fail if maxlen > INT_MAX.  */
+                   if (maxlen > INT_MAX)
+                     goto overflow;
 # define SNPRINTF_BUF(arg) \
                    switch (prefix_count)                                   \
                      {                                                     \
@@ -1382,6 +1394,15 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
        not have this limitation.  */
     return result;
 
+  overflow:
+    if (!(result == resultbuf || result == NULL))
+      free (result);
+    if (buf_malloced != NULL)
+      free (buf_malloced);
+    CLEANUP ();
+    errno = EOVERFLOW;
+    return NULL;
+
   out_of_memory:
     if (!(result == resultbuf || result == NULL))
       free (result);
index d25c4a6..a9d840d 100644 (file)
@@ -46,7 +46,9 @@ vsprintf (char *str, const char *format, va_list args)
 {
   char *output;
   size_t len;
-  size_t lenbuf = SIZE_MAX;
+  /* vasnprintf fails with EOVERFLOW when the buffer size argument is larger
+     than INT_MAX (if that fits into a 'size_t' at all).  */
+  size_t lenbuf = (SIZE_MAX < INT_MAX ? SIZE_MAX : INT_MAX);
 
   output = vasnprintf (str, &lenbuf, format, args);
   len = lenbuf;