diff options
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 271 |
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. */ |
| 1161 | static struct ablock *free_ablock; | 1202 | static 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 | ||
| 1422 | static INTERVAL interval_free_list; | 1469 | static 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 | ||
| 1426 | INTERVAL | 1491 | INTERVAL |
| @@ -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 | ||
| 2587 | static struct float_block *float_block; | 2732 | static 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 | ||
| 2691 | static struct Lisp_Cons *cons_free_list; | 2839 | static 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 | ||
| 2695 | void | 2856 | void |
| @@ -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 | ||
| 2705 | DEFUN ("cons", Fcons, Scons, 2, 2, 0, | 2867 | DEFUN ("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 | ||
| 2981 | Lisp_Object zero_vector; | 3146 | Lisp_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 | ||
| 2985 | static void | 3163 | static 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 * | |||
| 4561 | live_string_holding (struct mem_node *m, void *p) | 4769 | live_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 * | |||
| 4598 | live_cons_holding (struct mem_node *m, void *p) | 4815 | live_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 * | |||
| 4637 | live_symbol_holding (struct mem_node *m, void *p) | 4863 | live_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 * | |||
| 4684 | live_float_holding (struct mem_node *m, void *p) | 4918 | live_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 | } |