changeset 7218:0fd12ba5cfc6

Do the INT_MAX check only where size_t is converted to 'int'.
author Bruno Haible <bruno@clisp.org>
date Mon, 28 Aug 2006 16:04:14 +0000
parents 6f8e77bc9fde
children f9bfde719d72
files lib/ChangeLog lib/vasnprintf.c lib/vasprintf.c lib/vsnprintf.c
diffstat 4 files changed, 60 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/lib/ChangeLog
+++ b/lib/ChangeLog
@@ -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>
 
--- a/lib/vasnprintf.c
+++ b/lib/vasnprintf.c
@@ -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"
@@ -51,11 +51,6 @@
 /* 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 @@
       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);
--- a/lib/vasprintf.c
+++ b/lib/vasprintf.c
@@ -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
@@ -22,10 +22,17 @@
 /* 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 @@
   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;
 }
--- a/lib/vsnprintf.c
+++ b/lib/vsnprintf.c
@@ -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>
@@ -30,6 +32,11 @@
 
 #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 @@
 {
   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)
+    {
+      if (size)
+	{
+	  size_t pruned_len = (len < size ? len : size - 1);
+	  memcpy (str, output, pruned_len);
+	  str[pruned_len] = '\0';
+	}
 
-  if (output != str)
-    free (output);
+      free (output);
+    }
+
+  if (len > INT_MAX)
+    {
+      errno = EOVERFLOW;
+      return -1;
+    }
 
   return len;
 }