changeset 4740:892879324c9c

(SIZE_MAX) [!defined SIZE_MAX]: Define. (error_tail): Do not loop, reallocating temporary buffer, since the original size is big enough. This avoids one potential size overflow calculation. Check for size overflow when calculating temporary buffer size. Free temporary buffer when done, if it was allocated with malloc; this closes a memory leak.
author Paul Eggert <eggert@cs.ucla.edu>
date Fri, 26 Sep 2003 07:41:40 +0000
parents 04758f7475fd
children 09375b319a6a
files lib/error.c
diffstat 1 files changed, 16 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/lib/error.c
+++ b/lib/error.c
@@ -90,6 +90,10 @@
 char *strerror_r ();
 # endif
 
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
+
 /* The calling program should define program_name and set it to the
    name of the executing program.  */
 extern char *program_name;
@@ -142,40 +146,27 @@
     {
 # define ALLOCA_LIMIT 2000
       size_t len = strlen (message) + 1;
-      wchar_t *wmessage = NULL;
+      const wchar_t *wmessage = L"out of memory";
       mbstate_t st;
       size_t res;
       const char *tmp;
-
-      do
-	{
-	  if (len < ALLOCA_LIMIT)
-	    wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
-	  else
-	    {
-	      if (wmessage != NULL && len / 2 < ALLOCA_LIMIT)
-		wmessage = NULL;
+      wchar_t *wbuf = (len < ALLOCA_LIMIT
+		       ? (void *) alloca (len * sizeof *wbuf)
+		       : len <= SIZE_MAX / sizeof *wbuf
+		       ? malloc (len * sizeof *wbuf)
+		       : NULL);
 
-	      wmessage = (wchar_t *) realloc (wmessage,
-					      len * sizeof (wchar_t));
-
-	      if (wmessage == NULL)
-		{
-		  fputws_unlocked (L"out of memory\n", stderr);
-		  return;
-		}
-	    }
-
+      if (wbuf)
+	{
 	  memset (&st, '\0', sizeof (st));
 	  tmp =message;
+	  res = mbsrtowcs (wbuf, &tmp, len, &st);
+	  wmessage = res == (size_t) -1 ? L"???" : wbuf;
 	}
-      while ((res = mbsrtowcs (wmessage, &tmp, len, &st)) == len);
-
-      if (res == (size_t) -1)
-	/* The string cannot be converted.  */
-	wmessage = (wchar_t *) L"???";
 
       __vfwprintf (stderr, wmessage, args);
+      if (! (len < ALLOCA_LIMIT))
+	free (wbuf);
     }
   else
 #endif