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 437c58672a525b6cf75e3989799b290305d9957a..9ed357b2a328bff49583ad2e1683d94a9f9a7755 100644 (file)
@@ -1,3 +1,15 @@
+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>
 
index 3b496d2539d44f606cf4af569e3b1366b51dc759..b68c1bbb0614c57f6b4541cc0366c8b3dda5a2aa 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 149c29242cbb0fb25aaa10fc46964a512823feeb..91da8812b78d27f89e8112a2f15cadbc7f548f67 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 827397bff5672b676499252a336c3b6a5d700da0..af567d2cc0dc0eebde64227f3b847b7276e94780 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;
 }