summary refs log tree commit diff
path: root/malloc/malloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'malloc/malloc.c')
-rw-r--r--malloc/malloc.c308
1 files changed, 153 insertions, 155 deletions
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 3f4fd77807..d2112b159a 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -4196,191 +4196,188 @@ _int_free(mstate av, Void_t* mem)
   mchunkptr       fwd;         /* misc temp for linking */
 
 
-  /* free(0) has no effect */
-  if (mem != 0) {
-    const char *errstr = NULL;
+  const char *errstr = NULL;
 
-    p = mem2chunk(mem);
-    size = chunksize(p);
+  p = mem2chunk(mem);
+  size = chunksize(p);
 
-    /* Little security check which won't hurt performance: the
-       allocator never wrapps around at the end of the address space.
-       Therefore we can exclude some size values which might appear
-       here by accident or by "design" from some intruder.  */
-    if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0))
-      {
-	errstr = "free(): invalid pointer";
-      errout:
-	malloc_printerr (check_action, errstr, mem);
-	return;
-      }
+  /* Little security check which won't hurt performance: the
+     allocator never wrapps around at the end of the address space.
+     Therefore we can exclude some size values which might appear
+     here by accident or by "design" from some intruder.  */
+  if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0))
+    {
+      errstr = "free(): invalid pointer";
+    errout:
+      malloc_printerr (check_action, errstr, mem);
+      return;
+    }
 
-    check_inuse_chunk(av, p);
+  check_inuse_chunk(av, p);
 
-    /*
-      If eligible, place chunk on a fastbin so it can be found
-      and used quickly in malloc.
-    */
+  /*
+    If eligible, place chunk on a fastbin so it can be found
+    and used quickly in malloc.
+  */
 
-    if ((unsigned long)(size) <= (unsigned long)(av->max_fast)
+  if ((unsigned long)(size) <= (unsigned long)(av->max_fast)
 
 #if TRIM_FASTBINS
-        /*
-           If TRIM_FASTBINS set, don't place chunks
-           bordering top into fastbins
-        */
-        && (chunk_at_offset(p, size) != av->top)
-#endif
-        ) {
-
-      set_fastchunks(av);
-      fb = &(av->fastbins[fastbin_index(size)]);
-      /* Another simple check: make sure the top of the bin is not the
-	 record we are going to add (i.e., double free).  */
-      if (__builtin_expect (*fb == p, 0))
-	{
-	  errstr = "double free or corruption (fasttop)";
-	  goto errout;
-	}
-      p->fd = *fb;
-      *fb = p;
-    }
-
-    /*
-       Consolidate other non-mmapped chunks as they arrive.
-    */
+      /*
+	If TRIM_FASTBINS set, don't place chunks
+	bordering top into fastbins
+      */
+      && (chunk_at_offset(p, size) != av->top)
+#endif
+      ) {
 
-    else if (!chunk_is_mmapped(p)) {
-      nextchunk = chunk_at_offset(p, size);
+    set_fastchunks(av);
+    fb = &(av->fastbins[fastbin_index(size)]);
+    /* Another simple check: make sure the top of the bin is not the
+       record we are going to add (i.e., double free).  */
+    if (__builtin_expect (*fb == p, 0))
+      {
+	errstr = "double free or corruption (fasttop)";
+	goto errout;
+      }
+    p->fd = *fb;
+    *fb = p;
+  }
 
-      /* Lightweight tests: check whether the block is already the
-	 top block.  */
-      if (__builtin_expect (p == av->top, 0))
-	{
-	  errstr = "double free or corruption (top)";
-	  goto errout;
-	}
-      /* Or whether the next chunk is beyond the boundaries of the arena.  */
-      if (__builtin_expect (contiguous (av)
-			    && (char *) nextchunk
-			       >= ((char *) av->top + chunksize(av->top)), 0))
-	{
-	  errstr = "double free or corruption (out)";
-	  goto errout;
-	}
-      /* Or whether the block is actually not marked used.  */
-      if (__builtin_expect (!prev_inuse(nextchunk), 0))
-	{
-	  errstr = "double free or corruption (!prev)";
-	  goto errout;
-	}
+  /*
+    Consolidate other non-mmapped chunks as they arrive.
+  */
 
-      nextsize = chunksize(nextchunk);
-      assert(nextsize > 0);
+  else if (!chunk_is_mmapped(p)) {
+    nextchunk = chunk_at_offset(p, size);
 
-      /* consolidate backward */
-      if (!prev_inuse(p)) {
-        prevsize = p->prev_size;
-        size += prevsize;
-        p = chunk_at_offset(p, -((long) prevsize));
-        unlink(p, bck, fwd);
+    /* Lightweight tests: check whether the block is already the
+       top block.  */
+    if (__builtin_expect (p == av->top, 0))
+      {
+	errstr = "double free or corruption (top)";
+	goto errout;
+      }
+    /* Or whether the next chunk is beyond the boundaries of the arena.  */
+    if (__builtin_expect (contiguous (av)
+			  && (char *) nextchunk
+			  >= ((char *) av->top + chunksize(av->top)), 0))
+      {
+	errstr = "double free or corruption (out)";
+	goto errout;
+      }
+    /* Or whether the block is actually not marked used.  */
+    if (__builtin_expect (!prev_inuse(nextchunk), 0))
+      {
+	errstr = "double free or corruption (!prev)";
+	goto errout;
       }
 
-      if (nextchunk != av->top) {
-        /* get and clear inuse bit */
-        nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
-
-        /* consolidate forward */
-        if (!nextinuse) {
-          unlink(nextchunk, bck, fwd);
-          size += nextsize;
-        } else
-	  clear_inuse_bit_at_offset(nextchunk, 0);
-
-        /*
-          Place the chunk in unsorted chunk list. Chunks are
-          not placed into regular bins until after they have
-          been given one chance to be used in malloc.
-        */
+    nextsize = chunksize(nextchunk);
+    assert(nextsize > 0);
 
-        bck = unsorted_chunks(av);
-        fwd = bck->fd;
-        p->bk = bck;
-        p->fd = fwd;
-        bck->fd = p;
-        fwd->bk = p;
+    /* consolidate backward */
+    if (!prev_inuse(p)) {
+      prevsize = p->prev_size;
+      size += prevsize;
+      p = chunk_at_offset(p, -((long) prevsize));
+      unlink(p, bck, fwd);
+    }
 
-        set_head(p, size | PREV_INUSE);
-        set_foot(p, size);
+    if (nextchunk != av->top) {
+      /* get and clear inuse bit */
+      nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
 
-        check_free_chunk(av, p);
-      }
+      /* consolidate forward */
+      if (!nextinuse) {
+	unlink(nextchunk, bck, fwd);
+	size += nextsize;
+      } else
+	clear_inuse_bit_at_offset(nextchunk, 0);
 
       /*
-         If the chunk borders the current high end of memory,
-         consolidate into top
+	Place the chunk in unsorted chunk list. Chunks are
+	not placed into regular bins until after they have
+	been given one chance to be used in malloc.
       */
 
-      else {
-        size += nextsize;
-        set_head(p, size | PREV_INUSE);
-        av->top = p;
-        check_chunk(av, p);
-      }
+      bck = unsorted_chunks(av);
+      fwd = bck->fd;
+      p->bk = bck;
+      p->fd = fwd;
+      bck->fd = p;
+      fwd->bk = p;
 
-      /*
-        If freeing a large space, consolidate possibly-surrounding
-        chunks. Then, if the total unused topmost memory exceeds trim
-        threshold, ask malloc_trim to reduce top.
-
-        Unless max_fast is 0, we don't know if there are fastbins
-        bordering top, so we cannot tell for sure whether threshold
-        has been reached unless fastbins are consolidated.  But we
-        don't want to consolidate on each free.  As a compromise,
-        consolidation is performed if FASTBIN_CONSOLIDATION_THRESHOLD
-        is reached.
-      */
+      set_head(p, size | PREV_INUSE);
+      set_foot(p, size);
+
+      check_free_chunk(av, p);
+    }
+
+    /*
+      If the chunk borders the current high end of memory,
+      consolidate into top
+    */
 
-      if ((unsigned long)(size) >= FASTBIN_CONSOLIDATION_THRESHOLD) {
-        if (have_fastchunks(av))
-          malloc_consolidate(av);
+    else {
+      size += nextsize;
+      set_head(p, size | PREV_INUSE);
+      av->top = p;
+      check_chunk(av, p);
+    }
+
+    /*
+      If freeing a large space, consolidate possibly-surrounding
+      chunks. Then, if the total unused topmost memory exceeds trim
+      threshold, ask malloc_trim to reduce top.
+
+      Unless max_fast is 0, we don't know if there are fastbins
+      bordering top, so we cannot tell for sure whether threshold
+      has been reached unless fastbins are consolidated.  But we
+      don't want to consolidate on each free.  As a compromise,
+      consolidation is performed if FASTBIN_CONSOLIDATION_THRESHOLD
+      is reached.
+    */
 
-	if (av == &main_arena) {
+    if ((unsigned long)(size) >= FASTBIN_CONSOLIDATION_THRESHOLD) {
+      if (have_fastchunks(av))
+	malloc_consolidate(av);
+
+      if (av == &main_arena) {
 #ifndef MORECORE_CANNOT_TRIM
-	  if ((unsigned long)(chunksize(av->top)) >=
-	      (unsigned long)(mp_.trim_threshold))
-	    sYSTRIm(mp_.top_pad, av);
+	if ((unsigned long)(chunksize(av->top)) >=
+	    (unsigned long)(mp_.trim_threshold))
+	  sYSTRIm(mp_.top_pad, av);
 #endif
-	} else {
-	  /* Always try heap_trim(), even if the top chunk is not
-             large, because the corresponding heap might go away.  */
-	  heap_info *heap = heap_for_ptr(top(av));
+      } else {
+	/* Always try heap_trim(), even if the top chunk is not
+	   large, because the corresponding heap might go away.  */
+	heap_info *heap = heap_for_ptr(top(av));
 
-	  assert(heap->ar_ptr == av);
-	  heap_trim(heap, mp_.top_pad);
-	}
+	assert(heap->ar_ptr == av);
+	heap_trim(heap, mp_.top_pad);
       }
-
     }
-    /*
-      If the chunk was allocated via mmap, release via munmap(). Note
-      that if HAVE_MMAP is false but chunk_is_mmapped is true, then
-      user must have overwritten memory. There's nothing we can do to
-      catch this error unless MALLOC_DEBUG is set, in which case
-      check_inuse_chunk (above) will have triggered error.
-    */
 
-    else {
+  }
+  /*
+    If the chunk was allocated via mmap, release via munmap(). Note
+    that if HAVE_MMAP is false but chunk_is_mmapped is true, then
+    user must have overwritten memory. There's nothing we can do to
+    catch this error unless MALLOC_DEBUG is set, in which case
+    check_inuse_chunk (above) will have triggered error.
+  */
+
+  else {
 #if HAVE_MMAP
-      int ret;
-      INTERNAL_SIZE_T offset = p->prev_size;
-      mp_.n_mmaps--;
-      mp_.mmapped_mem -= (size + offset);
-      ret = munmap((char*)p - offset, size + offset);
-      /* munmap returns non-zero on failure */
-      assert(ret == 0);
+    int ret;
+    INTERNAL_SIZE_T offset = p->prev_size;
+    mp_.n_mmaps--;
+    mp_.mmapped_mem -= (size + offset);
+    ret = munmap((char*)p - offset, size + offset);
+    /* munmap returns non-zero on failure */
+    assert(ret == 0);
 #endif
-    }
   }
 }
 
@@ -4528,7 +4525,8 @@ _int_realloc(mstate av, Void_t* oldmem, size_t bytes)
 
 #if REALLOC_ZERO_BYTES_FREES
   if (bytes == 0) {
-    _int_free(av, oldmem);
+    if (oldmem != 0)
+      _int_free(av, oldmem);
     return 0;
   }
 #endif