about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2005-07-29 23:26:18 +0000
committerRoland McGrath <roland@gnu.org>2005-07-29 23:26:18 +0000
commitd89f44d0b3c8cef1c0a19f09c26640b0f4fbb47e (patch)
treeb281eeca737ee0b7ec3351ce55d6931ce86eb943
parent999a76bfdb718e2e84106094d4ef8d0cba2653d4 (diff)
downloadglibc-d89f44d0b3c8cef1c0a19f09c26640b0f4fbb47e.tar.gz
glibc-d89f44d0b3c8cef1c0a19f09c26640b0f4fbb47e.tar.xz
glibc-d89f44d0b3c8cef1c0a19f09c26640b0f4fbb47e.zip
2005-07-19 Ulrich Drepper <drepper@redhat.com>
	[BZ #1137]
	* misc/Makefile: Add rules to build and run tst-error1.
	* misc/tst-error1.c: New file.
	* misc/error.c: Fix memory leak and possibly endless loop.
-rw-r--r--misc/Makefile13
-rw-r--r--misc/error.c34
-rw-r--r--misc/tst-error1.c26
3 files changed, 66 insertions, 7 deletions
diff --git a/misc/Makefile b/misc/Makefile
index 862eb1b800..b4c106c0cb 100644
--- a/misc/Makefile
+++ b/misc/Makefile
@@ -65,6 +65,8 @@ routines := brk sbrk sstk ioctl \
 
 distribute := device-nrs.h
 
+generated := tst-error1.mtrace tst-error1-mem
+
 include ../Makeconfig
 
 aux := init-misc
@@ -73,7 +75,11 @@ install-lib := libbsd-compat.a libg.a
 endif
 gpl2lgpl := error.c error.h
 
-tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch
+tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \
+	 tst-error1
+ifeq (no,$(cross-compiling))
+tests: $(objpfx)tst-error1-mem
+endif
 
 CFLAGS-tsearch.c = $(uses-callbacks)
 CFLAGS-lsearch.c = $(uses-callbacks)
@@ -106,3 +112,8 @@ endif
 ifeq ($(build-bounded),yes)
 $(objpfx)tst-tsearch-bp: $(common-objpfx)math/libm_b.a
 endif
+
+tst-error1-ENV = MALLOC_TRACE=$(objpfx)tst-error1.mtrace
+tst-error1-ARGS = $(objpfx)tst-error1.out
+$(objpfx)tst-error1-mem: $(objpfx)tst-error1.out
+	$(common-objpfx)malloc/mtrace $(objpfx)tst-error1.mtrace > $@
diff --git a/misc/error.c b/misc/error.c
index 2501583366..b608913fae 100644
--- a/misc/error.c
+++ b/misc/error.c
@@ -74,6 +74,7 @@ unsigned int error_message_count;
 
 # define program_name program_invocation_name
 # include <errno.h>
+# include <limits.h>
 # include <libio/libioP.h>
 
 /* In GNU libc we want do not want to use the common name `error' directly.
@@ -182,14 +183,15 @@ error_tail (int status, int errnum, const char *message, va_list args)
       mbstate_t st;
       size_t res;
       const char *tmp;
+      bool use_malloc = false;
 
-      do
+      while (1)
 	{
-	  if (len < ALLOCA_LIMIT)
+	  if (__libc_use_alloca (len * sizeof (wchar_t)))
 	    wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
 	  else
 	    {
-	      if (wmessage != NULL && len / 2 < ALLOCA_LIMIT)
+	      if (!use_malloc)
 		wmessage = NULL;
 
 	      wchar_t *p = (wchar_t *) realloc (wmessage,
@@ -201,18 +203,38 @@ error_tail (int status, int errnum, const char *message, va_list args)
 		  return;
 		}
 	      wmessage = p;
+	      use_malloc = true;
 	    }
 
 	  memset (&st, '\0', sizeof (st));
 	  tmp = message;
+
+	  res = mbsrtowcs (wmessage, &tmp, len, &st);
+	  if (res != len)
+	    break;
+
+	  if (__builtin_expect (len >= SIZE_MAX / 2, 0))
+	    {
+	      /* This really should not happen if everything is fine.  */
+	      res = (size_t) -1;
+	      break;
+	    }
+
+	  len *= 2;
 	}
-      while ((res = mbsrtowcs (wmessage, &tmp, len, &st)) == len);
 
       if (res == (size_t) -1)
-	/* The string cannot be converted.  */
-	wmessage = (wchar_t *) L"???";
+	{
+	  /* The string cannot be converted.  */
+	  if (use_malloc)
+	    free (wmessage);
+	  wmessage = (wchar_t *) L"???";
+	}
 
       __vfwprintf (stderr, wmessage, args);
+
+      if (use_malloc)
+	free (wmessage);
     }
   else
 #  endif
diff --git a/misc/tst-error1.c b/misc/tst-error1.c
new file mode 100644
index 0000000000..e84843ed2f
--- /dev/null
+++ b/misc/tst-error1.c
@@ -0,0 +1,26 @@
+#include <error.h>
+#include <mcheck.h>
+#include <stdio.h>
+#include <string.h>
+#include <wchar.h>
+
+static int
+do_test (int argc, char *argv[])
+{
+  mtrace ();
+  (void) freopen (argc == 1 ? "/dev/stdout" : argv[1], "a", stderr);
+  /* Orient the stream.  */
+  fwprintf (stderr, L"hello world\n");
+  char buf[20000];
+  static const char str[] = "hello world! ";
+  for (int i = 0; i < 1000; ++i)
+    memcpy (&buf[i * (sizeof (str) - 1)], str, sizeof (str));
+  error (0, 0, str);
+  error (0, 0, buf);
+  error (0, 0, buf);
+  error (0, 0, str);
+  return 0;
+}
+
+#define TEST_FUNCTION do_test (argc, argv)
+#include "../test-skeleton.c"