about summary refs log tree commit diff
path: root/malloc
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2004-09-09 09:03:28 +0000
committerUlrich Drepper <drepper@redhat.com>2004-09-09 09:03:28 +0000
commit6bf4302e764e422656f4f7230619fe9ab481ae04 (patch)
treeb88163dc68307fbd46ecabfd7b59db1d1e15b489 /malloc
parent45ab54ce2db0751bfe1b30c044e1e6fffd1e017e (diff)
downloadglibc-6bf4302e764e422656f4f7230619fe9ab481ae04.tar.gz
glibc-6bf4302e764e422656f4f7230619fe9ab481ae04.tar.xz
glibc-6bf4302e764e422656f4f7230619fe9ab481ae04.zip
(_int_free): Add inexpensive double free and memory corruption tests. (malloc_printf_nc): Renamed to malloc_printerr. Second parameter is no format string anymore. Don't use stdio. Adjust all callers.
Diffstat (limited to 'malloc')
-rw-r--r--malloc/malloc.c74
1 files changed, 50 insertions, 24 deletions
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 4db40514d6..824b6cc3f4 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -283,6 +283,9 @@ extern "C" {
 /* For va_arg, va_start, va_end.  */
 #include <stdarg.h>
 
+/* For writev and struct iovec.  */
+#include <sys/uio.h>
+
 /*
   Debugging:
 
@@ -1501,7 +1504,7 @@ static size_t   mUSABLe(Void_t*);
 static void     mSTATs(void);
 static int      mALLOPt(int, int);
 static struct mallinfo mALLINFo(mstate);
-static void malloc_printf_nc(int action, const char *template, ...);
+static void malloc_printerr(int action, const char *str, void *ptr);
 
 static Void_t* internal_function mem2mem_check(Void_t *p, size_t sz);
 static int internal_function top_check(void);
@@ -1971,10 +1974,11 @@ typedef struct malloc_chunk* mbinptr;
   FD = P->fd;                                                          \
   BK = P->bk;                                                          \
   if (__builtin_expect (FD->bk != P || BK->fd != P, 0))                \
-    malloc_printf_nc (check_action,                                    \
-		      "corrupted double-linked list at %p!\n", P);     \
-  FD->bk = BK;                                                         \
-  BK->fd = FD;                                                         \
+    malloc_printerr (check_action, "corrupted double-linked list", P); \
+  else {                                                               \
+    FD->bk = BK;                                                       \
+    BK->fd = FD;                                                       \
+  }                                                                    \
 }
 
 /*
@@ -4177,7 +4181,7 @@ _int_free(mstate av, Void_t* mem)
        here by accident or by "design" from some intruder.  */
     if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0))
       {
-	malloc_printf_nc (check_action, "free(): invalid pointer %p!\n", mem);
+	malloc_printerr (check_action, "free(): invalid pointer", mem);
 	return;
       }
 
@@ -4205,7 +4209,8 @@ _int_free(mstate av, Void_t* mem)
 	 record we are going to add (i.e., double free).  */
       if (__builtin_expect (*fb == p, 0))
 	{
-	  malloc_printf_nc (check_action, "double free(%p)!\n", mem);
+	double_free:
+	  malloc_printerr (check_action, "double free or corruption", mem);
 	  return;
 	}
       p->fd = *fb;
@@ -4218,6 +4223,19 @@ _int_free(mstate av, Void_t* mem)
 
     else if (!chunk_is_mmapped(p)) {
       nextchunk = chunk_at_offset(p, size);
+
+      /* Lightweight tests: check whether the block is already the
+	 top block.  */
+      if (__builtin_expect (p == av->top, 0))
+	goto double_free;
+      /* Or whether the next chunk is beyond the boundaries of the arena.  */
+      if (__builtin_expect ((char *) nextchunk >= ((char *) av->top
+						   + chunksize(av->top)), 0))
+	goto double_free;
+      /* Or whether the block is actually not marked used.  */
+      if (__builtin_expect (!prev_inuse(nextchunk), 0))
+	goto double_free;
+
       nextsize = chunksize(nextchunk);
       assert(nextsize > 0);
 
@@ -5413,27 +5431,35 @@ int mALLOPt(param_number, value) int param_number; int value;
 /* Helper code.  */
 
 static void
-malloc_printf_nc(int action, const char *template, ...)
+malloc_printerr(int action, const char *str, void *ptr)
 {
   if (action & 1)
     {
-#ifdef _LIBC
-      _IO_flockfile (stderr);
-      int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
-      ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
-#endif
-
-      va_list ap;
-      va_start (ap, template);
-
-      vfprintf (stderr, template, ap);
-
-      va_end (ap);
+      /* output string will be ": ADDR ***\n"  */
+      static const char suffix[] = " ***\n";
+      static const char prefix[] = ": 0x";
+      char buf[sizeof (prefix) - 1 + sizeof (void *) * 2 + sizeof (suffix)];
+      char *cp;
+      if (action & 4)
+	cp = memcpy (&buf[sizeof (buf) - 2], "\n", 2);
+      else
+	{
+	  cp = memcpy (&buf[sizeof (buf) - sizeof (suffix)], suffix,
+		       sizeof (suffix));
+	  cp = _itoa_word ((unsigned long int) ptr, cp, 16, 0);
+	  while (cp > &buf[sizeof (prefix) - 1])
+	    *--cp = '0';
+	  cp = memcpy (buf, prefix, sizeof (prefix) - 1);
+	}
 
-#ifdef _LIBC
-      ((_IO_FILE *) stderr)->_flags2 |= old_flags2;
-      _IO_funlockfile (stderr);
-#endif
+      struct iovec iov[3];
+      iov[0].iov_base = (char *) "*** glibc detected *** ";
+      iov[0].iov_len = strlen (iov[0].iov_base);
+      iov[1].iov_base = (char *) str;
+      iov[1].iov_len = strlen (str);
+      iov[2].iov_base = cp;
+      iov[2].iov_len = &buf[sizeof (buf) - 1] - cp;
+      TEMP_FAILURE_RETRY (__writev (STDERR_FILENO, iov, 3));
     }
   if (action & 2)
     abort ();