2015-11-06 Florian Weimer <fweimer@redhat.com>
* malloc/malloc.c (__libc_free): Do not free chunks in corrupt
arenas.
(realloc_from_corrupt): New function.
(__libc_realloc): Call it for corrupt arenas.
@@ -2966,10 +2966,38 @@ __libc_free (void *mem)
}
ar_ptr = arena_for_chunk (p);
+
+ if (__glibc_unlikely (arena_is_corrupt (ar_ptr)))
+ /* Do nothing if the arena is known to be corrupt. */
+ return;
+
_int_free (ar_ptr, p, 0);
}
libc_hidden_def (__libc_free)
+/* Always make a copy to enlarge a chunk in a corrupt arena. The
+ chunk must not have been allocated with mmap. */
+static void *
+realloc_from_corrupt (void *oldmem, size_t bytes,
+ INTERNAL_SIZE_T oldsize)
+{
+ /* Size adjustment for the non-mmap case. */
+ oldsize -= SIZE_SZ;
+
+ /* Reuse the old chunk if possible. */
+ if (oldsize >= bytes)
+ return oldmem;
+
+ void *new_mem = __libc_malloc (bytes);
+ if (__glibc_unlikely (new_mem == NULL))
+ return NULL;
+ memcpy (new_mem, old_mem, oldsize);
+
+ /* Do not free the old object because the arena is known to be
+ corrupt. */
+ return new_mem;
+}
+
void *
__libc_realloc (void *oldmem, size_t bytes)
{
@@ -3041,6 +3069,9 @@ __libc_realloc (void *oldmem, size_t bytes)
return newmem;
}
+ if (__glibc_unlikely (arena_is_corrupt (ar_ptr)))
+ return realloc_from_corrupt (oldmem, bytes, oldsize);
+
(void) mutex_lock (&ar_ptr->mutex);
newp = _int_realloc (ar_ptr, oldp, oldsize, nb);