diff options
| author | Eli Zaretskii | 2014-03-03 18:46:36 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2014-03-03 18:46:36 +0200 |
| commit | bd650c24205a7a06f2786ad2226ed7cc19dbd69e (patch) | |
| tree | 4418f83f07b9be9bee587333c7422100af9f0bed /src/gmalloc.c | |
| parent | 19dae293f9fecea07c91440f0a33076c54d39b49 (diff) | |
| download | emacs-bd650c24205a7a06f2786ad2226ed7cc19dbd69e.tar.gz emacs-bd650c24205a7a06f2786ad2226ed7cc19dbd69e.zip | |
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
Diffstat (limited to 'src/gmalloc.c')
| -rw-r--r-- | src/gmalloc.c | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/src/gmalloc.c b/src/gmalloc.c index 12c2357de77..f8d0cfdc30a 100644 --- a/src/gmalloc.c +++ b/src/gmalloc.c | |||
| @@ -68,6 +68,10 @@ extern int posix_memalign (void **, size_t, size_t); | |||
| 68 | extern void malloc_enable_thread (void); | 68 | extern void malloc_enable_thread (void); |
| 69 | #endif | 69 | #endif |
| 70 | 70 | ||
| 71 | #ifdef emacs | ||
| 72 | extern void emacs_abort (void); | ||
| 73 | #endif | ||
| 74 | |||
| 71 | /* The allocator divides the heap into blocks of fixed size; large | 75 | /* The allocator divides the heap into blocks of fixed size; large |
| 72 | requests receive one or more whole blocks, and small requests | 76 | requests receive one or more whole blocks, and small requests |
| 73 | receive a fragment of a block. Fragment sizes are powers of two, | 77 | receive a fragment of a block. Fragment sizes are powers of two, |
| @@ -1595,7 +1599,7 @@ aligned_alloc (size_t alignment, size_t size) | |||
| 1595 | { | 1599 | { |
| 1596 | /* Reallocate the block with only as much excess as it needs. */ | 1600 | /* Reallocate the block with only as much excess as it needs. */ |
| 1597 | free (result); | 1601 | free (result); |
| 1598 | result = malloc (adj + size); | 1602 | result = malloc (size + alignment - adj); |
| 1599 | if (result == NULL) /* Impossible unless interrupted. */ | 1603 | if (result == NULL) /* Impossible unless interrupted. */ |
| 1600 | return NULL; | 1604 | return NULL; |
| 1601 | 1605 | ||
| @@ -1605,7 +1609,7 @@ aligned_alloc (size_t alignment, size_t size) | |||
| 1605 | different block with weaker alignment. If so, this block is too | 1609 | different block with weaker alignment. If so, this block is too |
| 1606 | short to contain SIZE after alignment correction. So we must | 1610 | short to contain SIZE after alignment correction. So we must |
| 1607 | try again and get another block, slightly larger. */ | 1611 | try again and get another block, slightly larger. */ |
| 1608 | } while (adj > lastadj); | 1612 | } while (adj < lastadj); |
| 1609 | 1613 | ||
| 1610 | if (adj != 0) | 1614 | if (adj != 0) |
| 1611 | { | 1615 | { |
| @@ -1787,6 +1791,22 @@ freehook (void *ptr) | |||
| 1787 | 1791 | ||
| 1788 | if (ptr) | 1792 | if (ptr) |
| 1789 | { | 1793 | { |
| 1794 | struct alignlist *l; | ||
| 1795 | |||
| 1796 | /* If the block was allocated by aligned_alloc, its real pointer | ||
| 1797 | to free is recorded in _aligned_blocks; find that. */ | ||
| 1798 | PROTECT_MALLOC_STATE (0); | ||
| 1799 | LOCK_ALIGNED_BLOCKS (); | ||
| 1800 | for (l = _aligned_blocks; l != NULL; l = l->next) | ||
| 1801 | if (l->aligned == ptr) | ||
| 1802 | { | ||
| 1803 | l->aligned = NULL; /* Mark the slot in the list as free. */ | ||
| 1804 | ptr = l->exact; | ||
| 1805 | break; | ||
| 1806 | } | ||
| 1807 | UNLOCK_ALIGNED_BLOCKS (); | ||
| 1808 | PROTECT_MALLOC_STATE (1); | ||
| 1809 | |||
| 1790 | hdr = ((struct hdr *) ptr) - 1; | 1810 | hdr = ((struct hdr *) ptr) - 1; |
| 1791 | checkhdr (hdr); | 1811 | checkhdr (hdr); |
| 1792 | hdr->magic = MAGICFREE; | 1812 | hdr->magic = MAGICFREE; |
| @@ -1878,7 +1898,11 @@ mabort (enum mcheck_status status) | |||
| 1878 | #else | 1898 | #else |
| 1879 | fprintf (stderr, "mcheck: %s\n", msg); | 1899 | fprintf (stderr, "mcheck: %s\n", msg); |
| 1880 | fflush (stderr); | 1900 | fflush (stderr); |
| 1901 | # ifdef emacs | ||
| 1902 | emacs_abort (); | ||
| 1903 | # else | ||
| 1881 | abort (); | 1904 | abort (); |
| 1905 | # endif | ||
| 1882 | #endif | 1906 | #endif |
| 1883 | } | 1907 | } |
| 1884 | 1908 | ||