changeset 8468:336e69863755

Fix endless loop when the given allocated size was > INT_MAX.
author Bruno Haible <bruno@clisp.org>
date Sun, 18 Mar 2007 00:31:50 +0000
parents 987ea3bfa3c5
children d2c38822872e
files ChangeLog lib/sprintf.c lib/vasnprintf.c lib/vsprintf.c
diffstat 4 files changed, 36 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+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.
--- a/lib/sprintf.c
+++ b/lib/sprintf.c
@@ -46,7 +46,9 @@
 {
   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);
--- a/lib/vasnprintf.c
+++ b/lib/vasnprintf.c
@@ -59,6 +59,11 @@
 # 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 @@
       {
 	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 @@
 		    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 @@
        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);
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -46,7 +46,9 @@
 {
   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;