aboutsummaryrefslogtreecommitdiffstats
path: root/src/gmalloc.c
diff options
context:
space:
mode:
authorEli Zaretskii2014-03-03 18:46:36 +0200
committerEli Zaretskii2014-03-03 18:46:36 +0200
commitbd650c24205a7a06f2786ad2226ed7cc19dbd69e (patch)
tree4418f83f07b9be9bee587333c7422100af9f0bed /src/gmalloc.c
parent19dae293f9fecea07c91440f0a33076c54d39b49 (diff)
downloademacs-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.c28
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);
68extern void malloc_enable_thread (void); 68extern void malloc_enable_thread (void);
69#endif 69#endif
70 70
71#ifdef emacs
72extern 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