aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c271
1 files changed, 263 insertions, 8 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 82e8901cf43..2975754124a 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -80,6 +80,37 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
80#include <valgrind/memcheck.h> 80#include <valgrind/memcheck.h>
81#endif 81#endif
82 82
83/* AddressSanitizer exposes additional functions for manually marking
84 memory as poisoned/unpoisoned. When ASan is enabled and the needed
85 header is available, memory is poisoned when:
86
87 * An ablock is freed (lisp_align_free), or ablocks are initially
88 allocated (lisp_align_malloc).
89 * An interval_block is initially allocated (make_interval).
90 * A dead INTERVAL is put on the interval free list
91 (sweep_intervals).
92 * A sdata is marked as dead (sweep_strings, pin_string).
93 * An sblock is initially allocated (allocate_string_data).
94 * A string_block is initially allocated (allocate_string).
95 * A dead string is put on string_free_list (sweep_strings).
96 * A float_block is initially allocated (make_float).
97 * A dead float is put on float_free_list.
98 * A cons_block is initially allocated (Fcons).
99 * A dead cons is put on cons_free_list (sweep_cons).
100 * A dead vector is put on vector_free_list (setup_on_free_list),
101 or a new vector block is allocated (allocate_vector_from_block).
102 Accordingly, objects reused from the free list are unpoisoned.
103
104 This feature can be disabled wtih the run-time flag
105 `allow_user_poisoning' set to zero. */
106#if ADDRESS_SANITIZER && defined HAVE_SANITIZER_ASAN_INTERFACE_H \
107 && !defined GC_ASAN_POISON_OBJECTS
108# define GC_ASAN_POISON_OBJECTS 1
109# include <sanitizer/asan_interface.h>
110#else
111# define GC_ASAN_POISON_OBJECTS 0
112#endif
113
83/* GC_CHECK_MARKED_OBJECTS means do sanity checks on allocated objects. 114/* GC_CHECK_MARKED_OBJECTS means do sanity checks on allocated objects.
84 We turn that on by default when ENABLE_CHECKING is defined; 115 We turn that on by default when ENABLE_CHECKING is defined;
85 define GC_CHECK_MARKED_OBJECTS to zero to disable. */ 116 define GC_CHECK_MARKED_OBJECTS to zero to disable. */
@@ -1157,6 +1188,16 @@ struct ablocks
1157 (1 & (intptr_t) ABLOCKS_BUSY (abase) ? abase : ((void **) (abase))[-1]) 1188 (1 & (intptr_t) ABLOCKS_BUSY (abase) ? abase : ((void **) (abase))[-1])
1158#endif 1189#endif
1159 1190
1191#if GC_ASAN_POISON_OBJECTS
1192# define ASAN_POISON_ABLOCK(b) \
1193 __asan_poison_memory_region (&(b)->x, sizeof ((b)->x))
1194# define ASAN_UNPOISON_ABLOCK(b) \
1195 __asan_unpoison_memory_region (&(b)->x, sizeof ((b)->x))
1196#else
1197# define ASAN_POISON_ABLOCK(b) ((void) 0)
1198# define ASAN_UNPOISON_ABLOCK(b) ((void) 0)
1199#endif
1200
1160/* The list of free ablock. */ 1201/* The list of free ablock. */
1161static struct ablock *free_ablock; 1202static struct ablock *free_ablock;
1162 1203
@@ -1235,6 +1276,7 @@ lisp_align_malloc (size_t nbytes, enum mem_type type)
1235 { 1276 {
1236 abase->blocks[i].abase = abase; 1277 abase->blocks[i].abase = abase;
1237 abase->blocks[i].x.next_free = free_ablock; 1278 abase->blocks[i].x.next_free = free_ablock;
1279 ASAN_POISON_ABLOCK (&abase->blocks[i]);
1238 free_ablock = &abase->blocks[i]; 1280 free_ablock = &abase->blocks[i];
1239 } 1281 }
1240 intptr_t ialigned = aligned; 1282 intptr_t ialigned = aligned;
@@ -1247,6 +1289,7 @@ lisp_align_malloc (size_t nbytes, enum mem_type type)
1247 eassert ((intptr_t) ABLOCKS_BUSY (abase) == aligned); 1289 eassert ((intptr_t) ABLOCKS_BUSY (abase) == aligned);
1248 } 1290 }
1249 1291
1292 ASAN_UNPOISON_ABLOCK (free_ablock);
1250 abase = ABLOCK_ABASE (free_ablock); 1293 abase = ABLOCK_ABASE (free_ablock);
1251 ABLOCKS_BUSY (abase) 1294 ABLOCKS_BUSY (abase)
1252 = (struct ablocks *) (2 + (intptr_t) ABLOCKS_BUSY (abase)); 1295 = (struct ablocks *) (2 + (intptr_t) ABLOCKS_BUSY (abase));
@@ -1278,6 +1321,7 @@ lisp_align_free (void *block)
1278#endif 1321#endif
1279 /* Put on free list. */ 1322 /* Put on free list. */
1280 ablock->x.next_free = free_ablock; 1323 ablock->x.next_free = free_ablock;
1324 ASAN_POISON_ABLOCK (ablock);
1281 free_ablock = ablock; 1325 free_ablock = ablock;
1282 /* Update busy count. */ 1326 /* Update busy count. */
1283 intptr_t busy = (intptr_t) ABLOCKS_BUSY (abase) - 2; 1327 intptr_t busy = (intptr_t) ABLOCKS_BUSY (abase) - 2;
@@ -1290,9 +1334,12 @@ lisp_align_free (void *block)
1290 bool aligned = busy; 1334 bool aligned = busy;
1291 struct ablock **tem = &free_ablock; 1335 struct ablock **tem = &free_ablock;
1292 struct ablock *atop = &abase->blocks[aligned ? ABLOCKS_SIZE : ABLOCKS_SIZE - 1]; 1336 struct ablock *atop = &abase->blocks[aligned ? ABLOCKS_SIZE : ABLOCKS_SIZE - 1];
1293
1294 while (*tem) 1337 while (*tem)
1295 { 1338 {
1339#if GC_ASAN_POISON_OBJECTS
1340 __asan_unpoison_memory_region (&(*tem)->x,
1341 sizeof ((*tem)->x));
1342#endif
1296 if (*tem >= (struct ablock *) abase && *tem < atop) 1343 if (*tem >= (struct ablock *) abase && *tem < atop)
1297 { 1344 {
1298 i++; 1345 i++;
@@ -1421,6 +1468,24 @@ static int interval_block_index = INTERVAL_BLOCK_SIZE;
1421 1468
1422static INTERVAL interval_free_list; 1469static INTERVAL interval_free_list;
1423 1470
1471#if GC_ASAN_POISON_OBJECTS
1472# define ASAN_POISON_INTERVAL_BLOCK(b) \
1473 __asan_poison_memory_region ((b)->intervals, \
1474 sizeof ((b)->intervals))
1475# define ASAN_UNPOISON_INTERVAL_BLOCK(b) \
1476 __asan_unpoison_memory_region ((b)->intervals, \
1477 sizeof ((b)->intervals))
1478# define ASAN_POISON_INTERVAL(i) \
1479 __asan_poison_memory_region ((i), sizeof (*(i)))
1480# define ASAN_UNPOISON_INTERVAL(i) \
1481 __asan_unpoison_memory_region ((i), sizeof (*(i)))
1482#else
1483# define ASAN_POISON_INTERVAL_BLOCK(b) ((void) 0)
1484# define ASAN_UNPOISON_INTERVAL_BLOCK(b) ((void) 0)
1485# define ASAN_POISON_INTERVAL(i) ((void) 0)
1486# define ASAN_UNPOISON_INTERVAL(i) ((void) 0)
1487#endif
1488
1424/* Return a new interval. */ 1489/* Return a new interval. */
1425 1490
1426INTERVAL 1491INTERVAL
@@ -1433,6 +1498,7 @@ make_interval (void)
1433 if (interval_free_list) 1498 if (interval_free_list)
1434 { 1499 {
1435 val = interval_free_list; 1500 val = interval_free_list;
1501 ASAN_UNPOISON_INTERVAL (val);
1436 interval_free_list = INTERVAL_PARENT (interval_free_list); 1502 interval_free_list = INTERVAL_PARENT (interval_free_list);
1437 } 1503 }
1438 else 1504 else
@@ -1443,10 +1509,12 @@ make_interval (void)
1443 = lisp_malloc (sizeof *newi, false, MEM_TYPE_NON_LISP); 1509 = lisp_malloc (sizeof *newi, false, MEM_TYPE_NON_LISP);
1444 1510
1445 newi->next = interval_block; 1511 newi->next = interval_block;
1512 ASAN_POISON_INTERVAL_BLOCK (newi);
1446 interval_block = newi; 1513 interval_block = newi;
1447 interval_block_index = 0; 1514 interval_block_index = 0;
1448 } 1515 }
1449 val = &interval_block->intervals[interval_block_index++]; 1516 val = &interval_block->intervals[interval_block_index++];
1517 ASAN_UNPOISON_INTERVAL (val);
1450 } 1518 }
1451 1519
1452 MALLOC_UNBLOCK_INPUT; 1520 MALLOC_UNBLOCK_INPUT;
@@ -1687,6 +1755,41 @@ init_strings (void)
1687 staticpro (&empty_multibyte_string); 1755 staticpro (&empty_multibyte_string);
1688} 1756}
1689 1757
1758#if GC_ASAN_POISON_OBJECTS
1759/* Prepare s for denoting a free sdata struct, i.e, poison all bytes
1760 in the flexible array member, except the first SDATA_OFFSET bytes.
1761 This is only effective for strings of size n where n > sdata_size(n).
1762 */
1763# define ASAN_PREPARE_DEAD_SDATA(s, size) \
1764 do { \
1765 __asan_poison_memory_region ((s), sdata_size ((size))); \
1766 __asan_unpoison_memory_region (&(((s))->string), \
1767 sizeof (struct Lisp_String *)); \
1768 __asan_unpoison_memory_region (&SDATA_NBYTES ((s)), \
1769 sizeof (SDATA_NBYTES ((s)))); \
1770 } while (false)
1771/* Prepare s for storing string data for NBYTES bytes. */
1772# define ASAN_PREPARE_LIVE_SDATA(s, nbytes) \
1773 __asan_unpoison_memory_region ((s), sdata_size ((nbytes)))
1774# define ASAN_POISON_SBLOCK_DATA(b, size) \
1775 __asan_poison_memory_region ((b)->data, (size))
1776# define ASAN_POISON_STRING_BLOCK(b) \
1777 __asan_poison_memory_region ((b)->strings, STRING_BLOCK_SIZE)
1778# define ASAN_UNPOISON_STRING_BLOCK(b) \
1779 __asan_unpoison_memory_region ((b)->strings, STRING_BLOCK_SIZE)
1780# define ASAN_POISON_STRING(s) \
1781 __asan_poison_memory_region ((s), sizeof (*(s)))
1782# define ASAN_UNPOISON_STRING(s) \
1783 __asan_unpoison_memory_region ((s), sizeof (*(s)))
1784#else
1785# define ASAN_PREPARE_DEAD_SDATA(s, size) ((void) 0)
1786# define ASAN_PREPARE_LIVE_SDATA(s, nbytes) ((void) 0)
1787# define ASAN_POISON_SBLOCK_DATA(b, size) ((void) 0)
1788# define ASAN_POISON_STRING_BLOCK(b) ((void) 0)
1789# define ASAN_UNPOISON_STRING_BLOCK(b) ((void) 0)
1790# define ASAN_POISON_STRING(s) ((void) 0)
1791# define ASAN_UNPOISON_STRING(s) ((void) 0)
1792#endif
1690 1793
1691#ifdef GC_CHECK_STRING_BYTES 1794#ifdef GC_CHECK_STRING_BYTES
1692 1795
@@ -1805,12 +1908,14 @@ allocate_string (void)
1805 NEXT_FREE_LISP_STRING (s) = string_free_list; 1908 NEXT_FREE_LISP_STRING (s) = string_free_list;
1806 string_free_list = s; 1909 string_free_list = s;
1807 } 1910 }
1911 ASAN_POISON_STRING_BLOCK (b);
1808 } 1912 }
1809 1913
1810 check_string_free_list (); 1914 check_string_free_list ();
1811 1915
1812 /* Pop a Lisp_String off the free-list. */ 1916 /* Pop a Lisp_String off the free-list. */
1813 s = string_free_list; 1917 s = string_free_list;
1918 ASAN_UNPOISON_STRING (s);
1814 string_free_list = NEXT_FREE_LISP_STRING (s); 1919 string_free_list = NEXT_FREE_LISP_STRING (s);
1815 1920
1816 MALLOC_UNBLOCK_INPUT; 1921 MALLOC_UNBLOCK_INPUT;
@@ -1870,6 +1975,7 @@ allocate_string_data (struct Lisp_String *s,
1870#endif 1975#endif
1871 1976
1872 b = lisp_malloc (size + GC_STRING_EXTRA, clearit, MEM_TYPE_NON_LISP); 1977 b = lisp_malloc (size + GC_STRING_EXTRA, clearit, MEM_TYPE_NON_LISP);
1978 ASAN_POISON_SBLOCK_DATA (b, size);
1873 1979
1874#ifdef DOUG_LEA_MALLOC 1980#ifdef DOUG_LEA_MALLOC
1875 if (!mmap_lisp_allowed_p ()) 1981 if (!mmap_lisp_allowed_p ())
@@ -1891,6 +1997,8 @@ allocate_string_data (struct Lisp_String *s,
1891 { 1997 {
1892 /* Not enough room in the current sblock. */ 1998 /* Not enough room in the current sblock. */
1893 b = lisp_malloc (SBLOCK_SIZE, false, MEM_TYPE_NON_LISP); 1999 b = lisp_malloc (SBLOCK_SIZE, false, MEM_TYPE_NON_LISP);
2000 ASAN_POISON_SBLOCK_DATA (b, SBLOCK_SIZE);
2001
1894 data = b->data; 2002 data = b->data;
1895 b->next = NULL; 2003 b->next = NULL;
1896 b->next_free = data; 2004 b->next_free = data;
@@ -1903,10 +2011,19 @@ allocate_string_data (struct Lisp_String *s,
1903 } 2011 }
1904 2012
1905 data = b->next_free; 2013 data = b->next_free;
2014
1906 if (clearit) 2015 if (clearit)
1907 memset (SDATA_DATA (data), 0, nbytes); 2016 {
2017#if GC_ASAN_POISON_OBJECTS
2018 /* We are accessing SDATA_DATA (data) before it gets
2019 * normally unpoisoned, so do it manually. */
2020 __asan_unpoison_memory_region (SDATA_DATA (data), nbytes);
2021#endif
2022 memset (SDATA_DATA (data), 0, nbytes);
2023 }
1908 } 2024 }
1909 2025
2026 ASAN_PREPARE_LIVE_SDATA (data, nbytes);
1910 data->string = s; 2027 data->string = s;
1911 b->next_free = (sdata *) ((char *) data + needed + GC_STRING_EXTRA); 2028 b->next_free = (sdata *) ((char *) data + needed + GC_STRING_EXTRA);
1912 eassert ((uintptr_t) b->next_free % alignof (sdata) == 0); 2029 eassert ((uintptr_t) b->next_free % alignof (sdata) == 0);
@@ -1998,12 +2115,16 @@ sweep_strings (void)
1998 int i, nfree = 0; 2115 int i, nfree = 0;
1999 struct Lisp_String *free_list_before = string_free_list; 2116 struct Lisp_String *free_list_before = string_free_list;
2000 2117
2118 ASAN_UNPOISON_STRING_BLOCK (b);
2119
2001 next = b->next; 2120 next = b->next;
2002 2121
2003 for (i = 0; i < STRING_BLOCK_SIZE; ++i) 2122 for (i = 0; i < STRING_BLOCK_SIZE; ++i)
2004 { 2123 {
2005 struct Lisp_String *s = b->strings + i; 2124 struct Lisp_String *s = b->strings + i;
2006 2125
2126 ASAN_UNPOISON_STRING (s);
2127
2007 if (s->u.s.data) 2128 if (s->u.s.data)
2008 { 2129 {
2009 /* String was not on free-list before. */ 2130 /* String was not on free-list before. */
@@ -2040,6 +2161,8 @@ sweep_strings (void)
2040 2161
2041 /* Put the string on the free-list. */ 2162 /* Put the string on the free-list. */
2042 NEXT_FREE_LISP_STRING (s) = string_free_list; 2163 NEXT_FREE_LISP_STRING (s) = string_free_list;
2164 ASAN_POISON_STRING (s);
2165 ASAN_PREPARE_DEAD_SDATA (data, SDATA_NBYTES (data));
2043 string_free_list = s; 2166 string_free_list = s;
2044 ++nfree; 2167 ++nfree;
2045 } 2168 }
@@ -2048,6 +2171,8 @@ sweep_strings (void)
2048 { 2171 {
2049 /* S was on the free-list before. Put it there again. */ 2172 /* S was on the free-list before. Put it there again. */
2050 NEXT_FREE_LISP_STRING (s) = string_free_list; 2173 NEXT_FREE_LISP_STRING (s) = string_free_list;
2174 ASAN_POISON_STRING (s);
2175
2051 string_free_list = s; 2176 string_free_list = s;
2052 ++nfree; 2177 ++nfree;
2053 } 2178 }
@@ -2174,6 +2299,7 @@ compact_small_strings (void)
2174 if (from != to) 2299 if (from != to)
2175 { 2300 {
2176 eassert (tb != b || to < from); 2301 eassert (tb != b || to < from);
2302 ASAN_PREPARE_LIVE_SDATA (to, nbytes);
2177 memmove (to, from, size + GC_STRING_EXTRA); 2303 memmove (to, from, size + GC_STRING_EXTRA);
2178 to->string->u.s.data = SDATA_DATA (to); 2304 to->string->u.s.data = SDATA_DATA (to);
2179 } 2305 }
@@ -2525,6 +2651,7 @@ pin_string (Lisp_Object string)
2525 memcpy (s->u.s.data, data, size); 2651 memcpy (s->u.s.data, data, size);
2526 old_sdata->string = NULL; 2652 old_sdata->string = NULL;
2527 SDATA_NBYTES (old_sdata) = size; 2653 SDATA_NBYTES (old_sdata) = size;
2654 ASAN_PREPARE_DEAD_SDATA (old_sdata, size);
2528 } 2655 }
2529 s->u.s.size_byte = -3; 2656 s->u.s.size_byte = -3;
2530} 2657}
@@ -2582,6 +2709,24 @@ struct float_block
2582#define XFLOAT_UNMARK(fptr) \ 2709#define XFLOAT_UNMARK(fptr) \
2583 UNSETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX ((fptr))) 2710 UNSETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX ((fptr)))
2584 2711
2712#if GC_ASAN_POISON_OBJECTS
2713# define ASAN_POISON_FLOAT_BLOCK(fblk) \
2714 __asan_poison_memory_region ((fblk)->floats, \
2715 sizeof ((fblk)->floats))
2716# define ASAN_UNPOISON_FLOAT_BLOCK(fblk) \
2717 __asan_unpoison_memory_region ((fblk)->floats, \
2718 sizeof ((fblk)->floats))
2719# define ASAN_POISON_FLOAT(p) \
2720 __asan_poison_memory_region ((p), sizeof (struct Lisp_Float))
2721# define ASAN_UNPOISON_FLOAT(p) \
2722 __asan_unpoison_memory_region ((p), sizeof (struct Lisp_Float))
2723#else
2724# define ASAN_POISON_FLOAT_BLOCK(fblk) ((void) 0)
2725# define ASAN_UNPOISON_FLOAT_BLOCK(fblk) ((void) 0)
2726# define ASAN_POISON_FLOAT(p) ((void) 0)
2727# define ASAN_UNPOISON_FLOAT(p) ((void) 0)
2728#endif
2729
2585/* Current float_block. */ 2730/* Current float_block. */
2586 2731
2587static struct float_block *float_block; 2732static struct float_block *float_block;
@@ -2606,6 +2751,7 @@ make_float (double float_value)
2606 if (float_free_list) 2751 if (float_free_list)
2607 { 2752 {
2608 XSETFLOAT (val, float_free_list); 2753 XSETFLOAT (val, float_free_list);
2754 ASAN_UNPOISON_FLOAT (float_free_list);
2609 float_free_list = float_free_list->u.chain; 2755 float_free_list = float_free_list->u.chain;
2610 } 2756 }
2611 else 2757 else
@@ -2616,9 +2762,11 @@ make_float (double float_value)
2616 = lisp_align_malloc (sizeof *new, MEM_TYPE_FLOAT); 2762 = lisp_align_malloc (sizeof *new, MEM_TYPE_FLOAT);
2617 new->next = float_block; 2763 new->next = float_block;
2618 memset (new->gcmarkbits, 0, sizeof new->gcmarkbits); 2764 memset (new->gcmarkbits, 0, sizeof new->gcmarkbits);
2765 ASAN_POISON_FLOAT_BLOCK (new);
2619 float_block = new; 2766 float_block = new;
2620 float_block_index = 0; 2767 float_block_index = 0;
2621 } 2768 }
2769 ASAN_UNPOISON_FLOAT (&float_block->floats[float_block_index]);
2622 XSETFLOAT (val, &float_block->floats[float_block_index]); 2770 XSETFLOAT (val, &float_block->floats[float_block_index]);
2623 float_block_index++; 2771 float_block_index++;
2624 } 2772 }
@@ -2690,6 +2838,19 @@ static int cons_block_index = CONS_BLOCK_SIZE;
2690 2838
2691static struct Lisp_Cons *cons_free_list; 2839static struct Lisp_Cons *cons_free_list;
2692 2840
2841#if GC_ASAN_POISON_OBJECTS
2842# define ASAN_POISON_CONS_BLOCK(b) \
2843 __asan_poison_memory_region ((b)->conses, sizeof ((b)->conses))
2844# define ASAN_POISON_CONS(p) \
2845 __asan_poison_memory_region ((p), sizeof (struct Lisp_Cons))
2846# define ASAN_UNPOISON_CONS(p) \
2847 __asan_unpoison_memory_region ((p), sizeof (struct Lisp_Cons))
2848#else
2849# define ASAN_POISON_CONS_BLOCK(b) ((void) 0)
2850# define ASAN_POISON_CONS(p) ((void) 0)
2851# define ASAN_UNPOISON_CONS(p) ((void) 0)
2852#endif
2853
2693/* Explicitly free a cons cell by putting it on the free-list. */ 2854/* Explicitly free a cons cell by putting it on the free-list. */
2694 2855
2695void 2856void
@@ -2700,6 +2861,7 @@ free_cons (struct Lisp_Cons *ptr)
2700 cons_free_list = ptr; 2861 cons_free_list = ptr;
2701 ptrdiff_t nbytes = sizeof *ptr; 2862 ptrdiff_t nbytes = sizeof *ptr;
2702 tally_consing (-nbytes); 2863 tally_consing (-nbytes);
2864 ASAN_POISON_CONS (ptr);
2703} 2865}
2704 2866
2705DEFUN ("cons", Fcons, Scons, 2, 2, 0, 2867DEFUN ("cons", Fcons, Scons, 2, 2, 0,
@@ -2712,6 +2874,7 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0,
2712 2874
2713 if (cons_free_list) 2875 if (cons_free_list)
2714 { 2876 {
2877 ASAN_UNPOISON_CONS (cons_free_list);
2715 XSETCONS (val, cons_free_list); 2878 XSETCONS (val, cons_free_list);
2716 cons_free_list = cons_free_list->u.s.u.chain; 2879 cons_free_list = cons_free_list->u.s.u.chain;
2717 } 2880 }
@@ -2722,10 +2885,12 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0,
2722 struct cons_block *new 2885 struct cons_block *new
2723 = lisp_align_malloc (sizeof *new, MEM_TYPE_CONS); 2886 = lisp_align_malloc (sizeof *new, MEM_TYPE_CONS);
2724 memset (new->gcmarkbits, 0, sizeof new->gcmarkbits); 2887 memset (new->gcmarkbits, 0, sizeof new->gcmarkbits);
2888 ASAN_POISON_CONS_BLOCK (new);
2725 new->next = cons_block; 2889 new->next = cons_block;
2726 cons_block = new; 2890 cons_block = new;
2727 cons_block_index = 0; 2891 cons_block_index = 0;
2728 } 2892 }
2893 ASAN_UNPOISON_CONS (&cons_block->conses[cons_block_index]);
2729 XSETCONS (val, &cons_block->conses[cons_block_index]); 2894 XSETCONS (val, &cons_block->conses[cons_block_index]);
2730 cons_block_index++; 2895 cons_block_index++;
2731 } 2896 }
@@ -2980,6 +3145,19 @@ static struct large_vector *large_vectors;
2980 3145
2981Lisp_Object zero_vector; 3146Lisp_Object zero_vector;
2982 3147
3148#if GC_ASAN_POISON_OBJECTS
3149# define ASAN_POISON_VECTOR_CONTENTS(v, bytes) \
3150 __asan_poison_memory_region ((v)->contents, (bytes))
3151# define ASAN_UNPOISON_VECTOR_CONTENTS(v, bytes) \
3152 __asan_unpoison_memory_region ((v)->contents, (bytes))
3153# define ASAN_UNPOISON_VECTOR_BLOCK(b) \
3154 __asan_unpoison_memory_region ((b)->data, sizeof ((b)->data))
3155#else
3156# define ASAN_POISON_VECTOR_CONTENTS(v, bytes) ((void) 0)
3157# define ASAN_UNPOISON_VECTOR_CONTENTS(v, bytes) ((void) 0)
3158# define ASAN_UNPOISON_VECTOR_BLOCK(b) ((void) 0)
3159#endif
3160
2983/* Common shortcut to setup vector on a free list. */ 3161/* Common shortcut to setup vector on a free list. */
2984 3162
2985static void 3163static void
@@ -2992,6 +3170,7 @@ setup_on_free_list (struct Lisp_Vector *v, ptrdiff_t nbytes)
2992 ptrdiff_t vindex = VINDEX (nbytes); 3170 ptrdiff_t vindex = VINDEX (nbytes);
2993 eassert (vindex < VECTOR_MAX_FREE_LIST_INDEX); 3171 eassert (vindex < VECTOR_MAX_FREE_LIST_INDEX);
2994 set_next_vector (v, vector_free_lists[vindex]); 3172 set_next_vector (v, vector_free_lists[vindex]);
3173 ASAN_POISON_VECTOR_CONTENTS (v, nbytes - header_size);
2995 vector_free_lists[vindex] = v; 3174 vector_free_lists[vindex] = v;
2996} 3175}
2997 3176
@@ -3039,6 +3218,7 @@ allocate_vector_from_block (ptrdiff_t nbytes)
3039 if (vector_free_lists[index]) 3218 if (vector_free_lists[index])
3040 { 3219 {
3041 vector = vector_free_lists[index]; 3220 vector = vector_free_lists[index];
3221 ASAN_UNPOISON_VECTOR_CONTENTS (vector, nbytes - header_size);
3042 vector_free_lists[index] = next_vector (vector); 3222 vector_free_lists[index] = next_vector (vector);
3043 return vector; 3223 return vector;
3044 } 3224 }
@@ -3052,12 +3232,18 @@ allocate_vector_from_block (ptrdiff_t nbytes)
3052 { 3232 {
3053 /* This vector is larger than requested. */ 3233 /* This vector is larger than requested. */
3054 vector = vector_free_lists[index]; 3234 vector = vector_free_lists[index];
3235 ASAN_UNPOISON_VECTOR_CONTENTS (vector, nbytes - header_size);
3055 vector_free_lists[index] = next_vector (vector); 3236 vector_free_lists[index] = next_vector (vector);
3056 3237
3057 /* Excess bytes are used for the smaller vector, 3238 /* Excess bytes are used for the smaller vector,
3058 which should be set on an appropriate free list. */ 3239 which should be set on an appropriate free list. */
3059 restbytes = index * roundup_size + VBLOCK_BYTES_MIN - nbytes; 3240 restbytes = index * roundup_size + VBLOCK_BYTES_MIN - nbytes;
3060 eassert (restbytes % roundup_size == 0); 3241 eassert (restbytes % roundup_size == 0);
3242#if GC_ASAN_POISON_OBJECTS
3243 /* Ensure that accessing excess bytes does not trigger ASan. */
3244 __asan_unpoison_memory_region (ADVANCE (vector, nbytes),
3245 restbytes);
3246#endif
3061 setup_on_free_list (ADVANCE (vector, nbytes), restbytes); 3247 setup_on_free_list (ADVANCE (vector, nbytes), restbytes);
3062 return vector; 3248 return vector;
3063 } 3249 }
@@ -3233,6 +3419,7 @@ sweep_vectors (void)
3233 for (vector = (struct Lisp_Vector *) block->data; 3419 for (vector = (struct Lisp_Vector *) block->data;
3234 VECTOR_IN_BLOCK (vector, block); vector = next) 3420 VECTOR_IN_BLOCK (vector, block); vector = next)
3235 { 3421 {
3422 ASAN_UNPOISON_VECTOR_BLOCK (block);
3236 if (XVECTOR_MARKED_P (vector)) 3423 if (XVECTOR_MARKED_P (vector))
3237 { 3424 {
3238 XUNMARK_VECTOR (vector); 3425 XUNMARK_VECTOR (vector);
@@ -3608,6 +3795,23 @@ struct symbol_block
3608 struct symbol_block *next; 3795 struct symbol_block *next;
3609}; 3796};
3610 3797
3798#if GC_ASAN_POISON_OBJECTS
3799# define ASAN_POISON_SYMBOL_BLOCK(s) \
3800 __asan_poison_memory_region ((s)->symbols, sizeof ((s)->symbols))
3801# define ASAN_UNPOISON_SYMBOL_BLOCK(s) \
3802 __asan_unpoison_memory_region ((s)->symbols, sizeof ((s)->symbols))
3803# define ASAN_POISON_SYMBOL(sym) \
3804 __asan_poison_memory_region ((sym), sizeof (*(sym)))
3805# define ASAN_UNPOISON_SYMBOL(sym) \
3806 __asan_unpoison_memory_region ((sym), sizeof (*(sym)))
3807
3808#else
3809# define ASAN_POISON_SYMBOL_BLOCK(s) ((void) 0)
3810# define ASAN_UNPOISON_SYMBOL_BLOCK(s) ((void) 0)
3811# define ASAN_POISON_SYMBOL(sym) ((void) 0)
3812# define ASAN_UNPOISON_SYMBOL(sym) ((void) 0)
3813#endif
3814
3611/* Current symbol block and index of first unused Lisp_Symbol 3815/* Current symbol block and index of first unused Lisp_Symbol
3612 structure in it. */ 3816 structure in it. */
3613 3817
@@ -3661,6 +3865,7 @@ Its value is void, and its function definition and property list are nil. */)
3661 3865
3662 if (symbol_free_list) 3866 if (symbol_free_list)
3663 { 3867 {
3868 ASAN_UNPOISON_SYMBOL (symbol_free_list);
3664 XSETSYMBOL (val, symbol_free_list); 3869 XSETSYMBOL (val, symbol_free_list);
3665 symbol_free_list = symbol_free_list->u.s.next; 3870 symbol_free_list = symbol_free_list->u.s.next;
3666 } 3871 }
@@ -3670,10 +3875,13 @@ Its value is void, and its function definition and property list are nil. */)
3670 { 3875 {
3671 struct symbol_block *new 3876 struct symbol_block *new
3672 = lisp_malloc (sizeof *new, false, MEM_TYPE_SYMBOL); 3877 = lisp_malloc (sizeof *new, false, MEM_TYPE_SYMBOL);
3878 ASAN_POISON_SYMBOL_BLOCK (new);
3673 new->next = symbol_block; 3879 new->next = symbol_block;
3674 symbol_block = new; 3880 symbol_block = new;
3675 symbol_block_index = 0; 3881 symbol_block_index = 0;
3676 } 3882 }
3883
3884 ASAN_UNPOISON_SYMBOL (&symbol_block->symbols[symbol_block_index]);
3677 XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index]); 3885 XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index]);
3678 symbol_block_index++; 3886 symbol_block_index++;
3679 } 3887 }
@@ -4561,6 +4769,11 @@ static struct Lisp_String *
4561live_string_holding (struct mem_node *m, void *p) 4769live_string_holding (struct mem_node *m, void *p)
4562{ 4770{
4563 eassert (m->type == MEM_TYPE_STRING); 4771 eassert (m->type == MEM_TYPE_STRING);
4772#if GC_ASAN_POISON_OBJECTS
4773 if (__asan_address_is_poisoned (p))
4774 return NULL;
4775#endif
4776
4564 struct string_block *b = m->start; 4777 struct string_block *b = m->start;
4565 char *cp = p; 4778 char *cp = p;
4566 ptrdiff_t offset = cp - (char *) &b->strings[0]; 4779 ptrdiff_t offset = cp - (char *) &b->strings[0];
@@ -4577,6 +4790,10 @@ live_string_holding (struct mem_node *m, void *p)
4577 || off == offsetof (struct Lisp_String, u.s.data)) 4790 || off == offsetof (struct Lisp_String, u.s.data))
4578 { 4791 {
4579 struct Lisp_String *s = p = cp -= off; 4792 struct Lisp_String *s = p = cp -= off;
4793#if GC_ASAN_POISON_OBJECTS
4794 if (__asan_region_is_poisoned (s, sizeof (*s)))
4795 return NULL;
4796#endif
4580 if (s->u.s.data) 4797 if (s->u.s.data)
4581 return s; 4798 return s;
4582 } 4799 }
@@ -4598,6 +4815,11 @@ static struct Lisp_Cons *
4598live_cons_holding (struct mem_node *m, void *p) 4815live_cons_holding (struct mem_node *m, void *p)
4599{ 4816{
4600 eassert (m->type == MEM_TYPE_CONS); 4817 eassert (m->type == MEM_TYPE_CONS);
4818#if GC_ASAN_POISON_OBJECTS
4819 if (__asan_address_is_poisoned (p))
4820 return NULL;
4821#endif
4822
4601 struct cons_block *b = m->start; 4823 struct cons_block *b = m->start;
4602 char *cp = p; 4824 char *cp = p;
4603 ptrdiff_t offset = cp - (char *) &b->conses[0]; 4825 ptrdiff_t offset = cp - (char *) &b->conses[0];
@@ -4615,6 +4837,10 @@ live_cons_holding (struct mem_node *m, void *p)
4615 || off == offsetof (struct Lisp_Cons, u.s.u.cdr)) 4837 || off == offsetof (struct Lisp_Cons, u.s.u.cdr))
4616 { 4838 {
4617 struct Lisp_Cons *s = p = cp -= off; 4839 struct Lisp_Cons *s = p = cp -= off;
4840#if GC_ASAN_POISON_OBJECTS
4841 if (__asan_region_is_poisoned (s, sizeof (*s)))
4842 return NULL;
4843#endif
4618 if (!deadp (s->u.s.car)) 4844 if (!deadp (s->u.s.car))
4619 return s; 4845 return s;
4620 } 4846 }
@@ -4637,6 +4863,10 @@ static struct Lisp_Symbol *
4637live_symbol_holding (struct mem_node *m, void *p) 4863live_symbol_holding (struct mem_node *m, void *p)
4638{ 4864{
4639 eassert (m->type == MEM_TYPE_SYMBOL); 4865 eassert (m->type == MEM_TYPE_SYMBOL);
4866#if GC_ASAN_POISON_OBJECTS
4867 if (__asan_address_is_poisoned (p))
4868 return NULL;
4869#endif
4640 struct symbol_block *b = m->start; 4870 struct symbol_block *b = m->start;
4641 char *cp = p; 4871 char *cp = p;
4642 ptrdiff_t offset = cp - (char *) &b->symbols[0]; 4872 ptrdiff_t offset = cp - (char *) &b->symbols[0];
@@ -4662,6 +4892,10 @@ live_symbol_holding (struct mem_node *m, void *p)
4662 || off == offsetof (struct Lisp_Symbol, u.s.next)) 4892 || off == offsetof (struct Lisp_Symbol, u.s.next))
4663 { 4893 {
4664 struct Lisp_Symbol *s = p = cp -= off; 4894 struct Lisp_Symbol *s = p = cp -= off;
4895#if GC_ASAN_POISON_OBJECTS
4896 if (__asan_region_is_poisoned (s, sizeof (*s)))
4897 return NULL;
4898#endif
4665 if (!deadp (s->u.s.function)) 4899 if (!deadp (s->u.s.function))
4666 return s; 4900 return s;
4667 } 4901 }
@@ -4684,6 +4918,11 @@ static struct Lisp_Float *
4684live_float_holding (struct mem_node *m, void *p) 4918live_float_holding (struct mem_node *m, void *p)
4685{ 4919{
4686 eassert (m->type == MEM_TYPE_FLOAT); 4920 eassert (m->type == MEM_TYPE_FLOAT);
4921#if GC_ASAN_POISON_OBJECTS
4922 if (__asan_address_is_poisoned (p))
4923 return NULL;
4924#endif
4925
4687 struct float_block *b = m->start; 4926 struct float_block *b = m->start;
4688 char *cp = p; 4927 char *cp = p;
4689 ptrdiff_t offset = cp - (char *) &b->floats[0]; 4928 ptrdiff_t offset = cp - (char *) &b->floats[0];
@@ -4698,8 +4937,12 @@ live_float_holding (struct mem_node *m, void *p)
4698 && (b != float_block 4937 && (b != float_block
4699 || offset / sizeof b->floats[0] < float_block_index)) 4938 || offset / sizeof b->floats[0] < float_block_index))
4700 { 4939 {
4701 p = cp - off; 4940 struct Lisp_Float *f = (struct Lisp_Float *) (cp - off);
4702 return p; 4941#if GC_ASAN_POISON_OBJECTS
4942 if (__asan_region_is_poisoned (f, sizeof (*f)))
4943 return NULL;
4944#endif
4945 return f;
4703 } 4946 }
4704 } 4947 }
4705 return NULL; 4948 return NULL;
@@ -7181,11 +7424,13 @@ sweep_conses (void)
7181 struct Lisp_Cons *acons = &cblk->conses[pos]; 7424 struct Lisp_Cons *acons = &cblk->conses[pos];
7182 if (!XCONS_MARKED_P (acons)) 7425 if (!XCONS_MARKED_P (acons))
7183 { 7426 {
7427 ASAN_UNPOISON_CONS (&cblk->conses[pos]);
7184 this_free++; 7428 this_free++;
7185 cblk->conses[pos].u.s.u.chain = cons_free_list; 7429 cblk->conses[pos].u.s.u.chain = cons_free_list;
7186 cons_free_list = &cblk->conses[pos]; 7430 cons_free_list = &cblk->conses[pos];
7187 cons_free_list->u.s.car = dead_object (); 7431 cons_free_list->u.s.car = dead_object ();
7188 } 7432 ASAN_POISON_CONS (&cblk->conses[pos]);
7433 }
7189 else 7434 else
7190 { 7435 {
7191 num_used++; 7436 num_used++;
@@ -7203,6 +7448,7 @@ sweep_conses (void)
7203 { 7448 {
7204 *cprev = cblk->next; 7449 *cprev = cblk->next;
7205 /* Unhook from the free list. */ 7450 /* Unhook from the free list. */
7451 ASAN_UNPOISON_CONS (&cblk->conses[0]);
7206 cons_free_list = cblk->conses[0].u.s.u.chain; 7452 cons_free_list = cblk->conses[0].u.s.u.chain;
7207 lisp_align_free (cblk); 7453 lisp_align_free (cblk);
7208 } 7454 }
@@ -7229,6 +7475,7 @@ sweep_floats (void)
7229 for (struct float_block *fblk; (fblk = *fprev); ) 7475 for (struct float_block *fblk; (fblk = *fprev); )
7230 { 7476 {
7231 int this_free = 0; 7477 int this_free = 0;
7478 ASAN_UNPOISON_FLOAT_BLOCK (fblk);
7232 for (int i = 0; i < lim; i++) 7479 for (int i = 0; i < lim; i++)
7233 { 7480 {
7234 struct Lisp_Float *afloat = &fblk->floats[i]; 7481 struct Lisp_Float *afloat = &fblk->floats[i];
@@ -7236,6 +7483,7 @@ sweep_floats (void)
7236 { 7483 {
7237 this_free++; 7484 this_free++;
7238 fblk->floats[i].u.chain = float_free_list; 7485 fblk->floats[i].u.chain = float_free_list;
7486 ASAN_POISON_FLOAT (&fblk->floats[i]);
7239 float_free_list = &fblk->floats[i]; 7487 float_free_list = &fblk->floats[i];
7240 } 7488 }
7241 else 7489 else
@@ -7252,7 +7500,8 @@ sweep_floats (void)
7252 { 7500 {
7253 *fprev = fblk->next; 7501 *fprev = fblk->next;
7254 /* Unhook from the free list. */ 7502 /* Unhook from the free list. */
7255 float_free_list = fblk->floats[0].u.chain; 7503 ASAN_UNPOISON_FLOAT (&fblk->floats[0]);
7504 float_free_list = fblk->floats[0].u.chain;
7256 lisp_align_free (fblk); 7505 lisp_align_free (fblk);
7257 } 7506 }
7258 else 7507 else
@@ -7278,13 +7527,14 @@ sweep_intervals (void)
7278 for (struct interval_block *iblk; (iblk = *iprev); ) 7527 for (struct interval_block *iblk; (iblk = *iprev); )
7279 { 7528 {
7280 int this_free = 0; 7529 int this_free = 0;
7281 7530 ASAN_UNPOISON_INTERVAL_BLOCK (iblk);
7282 for (int i = 0; i < lim; i++) 7531 for (int i = 0; i < lim; i++)
7283 { 7532 {
7284 if (!iblk->intervals[i].gcmarkbit) 7533 if (!iblk->intervals[i].gcmarkbit)
7285 { 7534 {
7286 set_interval_parent (&iblk->intervals[i], interval_free_list); 7535 set_interval_parent (&iblk->intervals[i], interval_free_list);
7287 interval_free_list = &iblk->intervals[i]; 7536 interval_free_list = &iblk->intervals[i];
7537 ASAN_POISON_INTERVAL (&iblk->intervals[i]);
7288 this_free++; 7538 this_free++;
7289 } 7539 }
7290 else 7540 else
@@ -7301,6 +7551,7 @@ sweep_intervals (void)
7301 { 7551 {
7302 *iprev = iblk->next; 7552 *iprev = iblk->next;
7303 /* Unhook from the free list. */ 7553 /* Unhook from the free list. */
7554 ASAN_UNPOISON_INTERVAL (&iblk->intervals[0]);
7304 interval_free_list = INTERVAL_PARENT (&iblk->intervals[0]); 7555 interval_free_list = INTERVAL_PARENT (&iblk->intervals[0]);
7305 lisp_free (iblk); 7556 lisp_free (iblk);
7306 } 7557 }
@@ -7330,6 +7581,8 @@ sweep_symbols (void)
7330 7581
7331 for (sblk = symbol_block; sblk; sblk = *sprev) 7582 for (sblk = symbol_block; sblk; sblk = *sprev)
7332 { 7583 {
7584 ASAN_UNPOISON_SYMBOL_BLOCK (sblk);
7585
7333 int this_free = 0; 7586 int this_free = 0;
7334 struct Lisp_Symbol *sym = sblk->symbols; 7587 struct Lisp_Symbol *sym = sblk->symbols;
7335 struct Lisp_Symbol *end = sym + lim; 7588 struct Lisp_Symbol *end = sym + lim;
@@ -7351,7 +7604,8 @@ sweep_symbols (void)
7351 sym->u.s.next = symbol_free_list; 7604 sym->u.s.next = symbol_free_list;
7352 symbol_free_list = sym; 7605 symbol_free_list = sym;
7353 symbol_free_list->u.s.function = dead_object (); 7606 symbol_free_list->u.s.function = dead_object ();
7354 ++this_free; 7607 ASAN_POISON_SYMBOL (sym);
7608 ++this_free;
7355 } 7609 }
7356 else 7610 else
7357 { 7611 {
@@ -7370,6 +7624,7 @@ sweep_symbols (void)
7370 { 7624 {
7371 *sprev = sblk->next; 7625 *sprev = sblk->next;
7372 /* Unhook from the free list. */ 7626 /* Unhook from the free list. */
7627 ASAN_UNPOISON_SYMBOL (&sblk->symbols[0]);
7373 symbol_free_list = sblk->symbols[0].u.s.next; 7628 symbol_free_list = sblk->symbols[0].u.s.next;
7374 lisp_free (sblk); 7629 lisp_free (sblk);
7375 } 7630 }