Do the INT_MAX check only where size_t is converted to 'int'.
authorBruno Haible <bruno@clisp.org>
Mon, 28 Aug 2006 16:04:14 +0000 (16:04 +0000)
committerBruno Haible <bruno@clisp.org>
Mon, 28 Aug 2006 16:04:14 +0000 (16:04 +0000)
lib/ChangeLog
lib/vasnprintf.c
lib/vasprintf.c
lib/vsnprintf.c

index 437c586..9ed357b 100644 (file)
@@ -1,4 +1,16 @@
 2006-08-26  Bruno Haible  <bruno@clisp.org>
+
+       * vasnprintf.c (EOVERFLOW): Remove definition.
+       (VASNPRINTF): Return a string of length > INT_MAX without failing.
+       * vasprintf.c: Include errno.h, limits.h.
+       (EOVERFLOW): New fallback definition.
+       (vasprintf): Test here whether the string length is > INT_MAX.
+       * vsnprintf.c: Include errno.h, limits.h.
+       (EOVERFLOW): New fallback definition.
+       (vsnprintf): Fix bug when generated string was too long for the buffer.
+       Test here whether the string length is > INT_MAX.
+
+2006-08-26  Bruno Haible  <bruno@clisp.org>
             Simon Josefsson  <jas@extundo.com>
 
        BeOS portability.
index 3b496d2..b68c1bb 100644 (file)
@@ -40,7 +40,7 @@
 #include <stdlib.h>    /* abort(), malloc(), realloc(), free() */
 #include <string.h>    /* memcpy(), strlen() */
 #include <errno.h>     /* errno */
-#include <limits.h>    /* CHAR_BIT, INT_MAX */
+#include <limits.h>    /* CHAR_BIT */
 #include <float.h>     /* DBL_MAX_EXP, LDBL_MAX_EXP */
 #if WIDE_CHAR_VERSION
 # include "wprintf-parse.h"
 /* Checked size_t computations.  */
 #include "xsize.h"
 
-/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW.  */
-#ifndef EOVERFLOW
-# define EOVERFLOW E2BIG
-#endif
-
 #ifdef HAVE_WCHAR_T
 # ifdef HAVE_WCSLEN
 #  define local_wcslen wcslen
@@ -869,19 +864,12 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
       free (buf_malloced);
     CLEANUP ();
     *lengthp = length;
-    if (length > INT_MAX)
-      goto length_overflow;
+    /* Note that we can produce a big string of a length > INT_MAX.  POSIX
+       says that snprintf() fails with errno = EOVERFLOW in this case, but
+       that's only because snprintf() returns an 'int'.  This function does
+       not have this limitation.  */
     return result;
 
-  length_overflow:
-    /* We could produce such a big string, but its length doesn't fit into
-       an 'int'.  POSIX says that snprintf() fails with errno = EOVERFLOW in
-       this case.  */
-    if (result != resultbuf)
-      free (result);
-    errno = EOVERFLOW;
-    return NULL;
-
   out_of_memory:
     if (!(result == resultbuf || result == NULL))
       free (result);
index 149c292..91da881 100644 (file)
@@ -1,5 +1,5 @@
 /* Formatted output to strings.
-   Copyright (C) 1999, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2002, 2006 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 /* Specification.  */
 #include "vasprintf.h"
 
+#include <errno.h>
+#include <limits.h>
 #include <stdlib.h>
 
 #include "vasnprintf.h"
 
+/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW.  */
+#ifndef EOVERFLOW
+# define EOVERFLOW E2BIG
+#endif
+
 int
 vasprintf (char **resultp, const char *format, va_list args)
 {
@@ -34,9 +41,14 @@ vasprintf (char **resultp, const char *format, va_list args)
   if (result == NULL)
     return -1;
 
+  if (length > INT_MAX)
+    {
+      free (result);
+      errno = EOVERFLOW;
+      return -1;
+    }
+
   *resultp = result;
-  /* Return the number of resulting bytes, excluding the trailing NUL.
-     If it wouldn't fit in an 'int', vasnprintf() would have returned NULL
-     and set errno to EOVERFLOW.  */
+  /* Return the number of resulting bytes, excluding the trailing NUL.  */
   return length;
 }
index 827397b..af567d2 100644 (file)
@@ -1,5 +1,5 @@
 /* Formatted output to strings.
-   Copyright (C) 2004 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2006 Free Software Foundation, Inc.
    Written by Simon Josefsson and Yoann Vandoorselaere <yoann@prelude-ids.org>.
 
    This program is free software; you can redistribute it and/or modify
@@ -23,6 +23,8 @@
 /* Specification.  */
 #include "vsnprintf.h"
 
+#include <errno.h>
+#include <limits.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 
 #include "vasnprintf.h"
 
+/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW.  */
+#ifndef EOVERFLOW
+# define EOVERFLOW E2BIG
+#endif
+
 /* Print formatted output to string STR.  Similar to vsprintf, but
    additional length SIZE limit how much is written into STR.  Returns
    string length of formatted string (which may be larger than SIZE).
@@ -40,19 +47,31 @@ vsnprintf (char *str, size_t size, const char *format, va_list args)
 {
   char *output;
   size_t len;
+  size_t lenbuf = size;
 
-  len = size;
-  output = vasnprintf (str, &len, format, args);
+  output = vasnprintf (str, &lenbuf, format, args);
+  len = lenbuf;
 
   if (!output)
     return -1;
 
-  if (str != NULL)
-    if (len > size - 1) /* equivalent to: (size > 0 && len >= size) */
-      str[size - 1] = '\0';
-
   if (output != str)
-    free (output);
+    {
+      if (size)
+       {
+         size_t pruned_len = (len < size ? len : size - 1);
+         memcpy (str, output, pruned_len);
+         str[pruned_len] = '\0';
+       }
+
+      free (output);
+    }
+
+  if (len > INT_MAX)
+    {
+      errno = EOVERFLOW;
+      return -1;
+    }
 
   return len;
 }