Commit bd650c24 authored by Eli Zaretskii's avatar Eli Zaretskii

Fix crashes in lisp_align_free in a build with GC_MCHECK.

 src/gmalloc.c (aligned_alloc): Fix adjustment of size of the
 allocated buffer due to alignment.
 (freehook): If the block to be freed was allocated by
 'aligned_alloc', find its real pointer before calling 'free'.
 (mabort) [emacs]: Call 'emacs_abort', not 'abort', to provide a
 backtrace.

Fixes: debbugs:16901
parent 19dae293
2014-03-03 Eli Zaretskii <eliz@gnu.org>
* gmalloc.c (aligned_alloc): Fix adjustment of size of the
allocated buffer due to alignment.
(freehook): If the block to be freed was allocated by
'aligned_alloc', find its real pointer before calling 'free'.
(Bug#16901)
(mabort) [emacs]: Call 'emacs_abort', not 'abort', to provide a
backtrace.
2014-03-03 Dmitry Antipov <dmantipov@yandex.ru>
* font.c (toplevel): Adjust comment about font cache layout.
......
......@@ -68,6 +68,10 @@ extern int posix_memalign (void **, size_t, size_t);
extern void malloc_enable_thread (void);
#endif
#ifdef emacs
extern void emacs_abort (void);
#endif
/* The allocator divides the heap into blocks of fixed size; large
requests receive one or more whole blocks, and small requests
receive a fragment of a block. Fragment sizes are powers of two,
......@@ -1595,7 +1599,7 @@ aligned_alloc (size_t alignment, size_t size)
{
/* Reallocate the block with only as much excess as it needs. */
free (result);
result = malloc (adj + size);
result = malloc (size + alignment - adj);
if (result == NULL) /* Impossible unless interrupted. */
return NULL;
......@@ -1605,7 +1609,7 @@ aligned_alloc (size_t alignment, size_t size)
different block with weaker alignment. If so, this block is too
short to contain SIZE after alignment correction. So we must
try again and get another block, slightly larger. */
} while (adj > lastadj);
} while (adj < lastadj);
if (adj != 0)
{
......@@ -1787,6 +1791,22 @@ freehook (void *ptr)
if (ptr)
{
struct alignlist *l;
/* If the block was allocated by aligned_alloc, its real pointer
to free is recorded in _aligned_blocks; find that. */
PROTECT_MALLOC_STATE (0);
LOCK_ALIGNED_BLOCKS ();
for (l = _aligned_blocks; l != NULL; l = l->next)
if (l->aligned == ptr)
{
l->aligned = NULL; /* Mark the slot in the list as free. */
ptr = l->exact;
break;
}
UNLOCK_ALIGNED_BLOCKS ();
PROTECT_MALLOC_STATE (1);
hdr = ((struct hdr *) ptr) - 1;
checkhdr (hdr);
hdr->magic = MAGICFREE;
......@@ -1878,7 +1898,11 @@ mabort (enum mcheck_status status)
#else
fprintf (stderr, "mcheck: %s\n", msg);
fflush (stderr);
# ifdef emacs
emacs_abort ();
# else
abort ();
# endif
#endif
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment