This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

memory leak, buffer-size-calculation overflow in error.c


While auditing gnulib code for buffer size calculation overflows, I
noticed that misc/error.c had two such problems, along with a memory leak.
Here is a proposed patch.

2003-09-26  Paul Eggert  <eggert@twinsun.com>

	* error.c (SIZE_MAX) [!defined SIZE_MAX]: Define.
	(error_tail): Do not loop, reallocating temporary buffer, since
	the output cannot contain more wide characters than the input
	contains bytes, the size must be big enough already.  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 plugs a memory
	leak.  Remove casts from void * to pointers, that are no longer
	needed now that we're assuming C89 or better.

--- misc/error.c	Wed Sep  3 13:11:51 2003
+++ misc/error.c-fix	Fri Sep 26 00:49:03 2003
@@ -103,6 +103,10 @@ extern void __error_at_line (int status,
 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;
@@ -178,40 +182,27 @@ error_tail (int status, int errnum, cons
     {
 #   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;
+      wchar_t *wbuf = (len < ALLOCA_LIMIT
+		       ? (void *) alloca (len * sizeof *wbuf)
+		       : len <= SIZE_MAX / sizeof *wbuf
+		       ? malloc (len * sizeof *wbuf)
+		       : NULL);
 
-      do
+      if (wbuf)
 	{
-	  if (len < ALLOCA_LIMIT)
-	    wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
-	  else
-	    {
-	      if (wmessage != NULL && len / 2 < ALLOCA_LIMIT)
-		wmessage = NULL;
-
-	      wmessage = (wchar_t *) realloc (wmessage,
-					      len * sizeof (wchar_t));
-
-	      if (wmessage == NULL)
-		{
-		  fputws_unlocked (L"out of memory\n", stderr);
-		  return;
-		}
-	    }
-
 	  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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]