Cheng Shao pushed to branch wip/terrorjack/asan at Glasgow Haskell Compiler / GHC
Commits:
-
d80037c2
by Cheng Shao at 2026-07-06T08:10:12+00:00
-
b7450c9d
by Cheng Shao at 2026-07-06T08:10:17+00:00
-
6cf654e3
by Cheng Shao at 2026-07-06T08:10:17+00:00
-
709b95b5
by Cheng Shao at 2026-07-06T08:10:17+00:00
-
5ca629c5
by Cheng Shao at 2026-07-06T08:10:17+00:00
-
2ad71829
by Cheng Shao at 2026-07-06T08:10:17+00:00
-
73ce0ca8
by Cheng Shao at 2026-07-06T08:10:17+00:00
-
a79ae1c7
by Cheng Shao at 2026-07-06T08:10:17+00:00
12 changed files:
- rts/Hash.c
- rts/Task.c
- rts/include/Stg.h
- + rts/include/rts/ASANUtils.h
- rts/rts.cabal
- rts/sm/BlockAlloc.c
- rts/sm/GCUtils.c
- rts/sm/MBlock.c
- rts/sm/NonMoving.c
- rts/sm/NonMovingAllocate.c
- rts/sm/NonMovingSweep.c
- rts/sm/Storage.c
Changes:
| ... | ... | @@ -283,6 +283,7 @@ allocHashList (HashTable *table) |
| 283 | 283 | if (table->freeList != NULL) {
|
| 284 | 284 | HashList *hl = table->freeList;
|
| 285 | 285 | table->freeList = hl->next;
|
| 286 | + __asan_unpoison_memory_region(hl, offsetof(HashList, next));
|
|
| 286 | 287 | return hl;
|
| 287 | 288 | } else {
|
| 288 | 289 | /* We allocate one block of memory which contains:
|
| ... | ... | @@ -302,8 +303,11 @@ allocHashList (HashTable *table) |
| 302 | 303 | |
| 303 | 304 | table->freeList = hl + 1;
|
| 304 | 305 | HashList *p = table->freeList;
|
| 305 | - for (; p < hl + HCHUNK - 1; p++)
|
|
| 306 | + for (; p < hl + HCHUNK - 1; p++) {
|
|
| 307 | + __asan_poison_memory_region(p, offsetof(HashList, next));
|
|
| 306 | 308 | p->next = p + 1;
|
| 309 | + }
|
|
| 310 | + __asan_poison_memory_region(p, offsetof(HashList, next));
|
|
| 307 | 311 | p->next = NULL;
|
| 308 | 312 | return hl;
|
| 309 | 313 | }
|
| ... | ... | @@ -318,6 +322,7 @@ freeHashList (HashTable *table, HashList *hl) |
| 318 | 322 | // HashListChunks.
|
| 319 | 323 | hl->next = table->freeList;
|
| 320 | 324 | table->freeList = hl;
|
| 325 | + __asan_poison_memory_region(hl, offsetof(HashList, next));
|
|
| 321 | 326 | }
|
| 322 | 327 | |
| 323 | 328 | STATIC_INLINE void
|
| ... | ... | @@ -388,9 +393,10 @@ removeHashTable_inlined(HashTable *table, StgWord key, const void *data, |
| 388 | 393 | table->dir[segment][index] = hl->next;
|
| 389 | 394 | else
|
| 390 | 395 | prev->next = hl->next;
|
| 396 | + void *hl_data = (void*)hl->data;
|
|
| 391 | 397 | freeHashList(table,hl);
|
| 392 | 398 | table->kcount--;
|
| 393 | - return (void *) hl->data;
|
|
| 399 | + return hl_data;
|
|
| 394 | 400 | }
|
| 395 | 401 | prev = hl;
|
| 396 | 402 | }
|
| ... | ... | @@ -183,6 +183,7 @@ freeTask (Task *task) |
| 183 | 183 | stgFree(incall);
|
| 184 | 184 | }
|
| 185 | 185 | for (incall = task->spare_incalls; incall != NULL; incall = next) {
|
| 186 | + __asan_unpoison_memory_region(incall, sizeof(InCall));
|
|
| 186 | 187 | next = incall->next;
|
| 187 | 188 | stgFree(incall);
|
| 188 | 189 | }
|
| ... | ... | @@ -252,6 +253,7 @@ newInCall (Task *task) |
| 252 | 253 | |
| 253 | 254 | if (task->spare_incalls != NULL) {
|
| 254 | 255 | incall = task->spare_incalls;
|
| 256 | + __asan_unpoison_memory_region(incall, sizeof(InCall));
|
|
| 255 | 257 | task->spare_incalls = incall->next;
|
| 256 | 258 | task->n_spare_incalls--;
|
| 257 | 259 | } else {
|
| ... | ... | @@ -283,6 +285,7 @@ endInCall (Task *task) |
| 283 | 285 | stgFree(incall);
|
| 284 | 286 | } else {
|
| 285 | 287 | incall->next = task->spare_incalls;
|
| 288 | + __asan_poison_memory_region(incall, sizeof(InCall));
|
|
| 286 | 289 | task->spare_incalls = incall;
|
| 287 | 290 | task->n_spare_incalls++;
|
| 288 | 291 | }
|
| ... | ... | @@ -331,6 +331,7 @@ external prototype return neither of these types to workaround #11395. |
| 331 | 331 | #include "stg/MachRegsForHost.h"
|
| 332 | 332 | #include "stg/Regs.h"
|
| 333 | 333 | #include "stg/Ticky.h"
|
| 334 | +#include "rts/ASANUtils.h"
|
|
| 334 | 335 | #include "rts/TSANUtils.h"
|
| 335 | 336 | |
| 336 | 337 | #if IN_STG_CODE
|
| 1 | +#pragma once
|
|
| 2 | + |
|
| 3 | +#if defined(__SANITIZE_ADDRESS__)
|
|
| 4 | +#define ASAN_ENABLED
|
|
| 5 | +#elif defined(__has_feature)
|
|
| 6 | +#if __has_feature(address_sanitizer)
|
|
| 7 | +#define ASAN_ENABLED
|
|
| 8 | +#endif
|
|
| 9 | +#endif
|
|
| 10 | + |
|
| 11 | +#if defined(ASAN_ENABLED)
|
|
| 12 | +#include <sanitizer/asan_interface.h>
|
|
| 13 | +#else
|
|
| 14 | + |
|
| 15 | +#include <stddef.h>
|
|
| 16 | + |
|
| 17 | +static inline void __asan_poison_memory_region(void const volatile *addr
|
|
| 18 | + __attribute__((unused)),
|
|
| 19 | + size_t size
|
|
| 20 | + __attribute__((unused))) {}
|
|
| 21 | + |
|
| 22 | +static inline void __asan_unpoison_memory_region(void const volatile *addr
|
|
| 23 | + __attribute__((unused)),
|
|
| 24 | + size_t size
|
|
| 25 | + __attribute__((unused))) {}
|
|
| 26 | + |
|
| 27 | +#endif |
| ... | ... | @@ -292,6 +292,7 @@ library |
| 292 | 292 | -- ^ generated
|
| 293 | 293 | rts/ghc_ffi.h
|
| 294 | 294 | rts/Adjustor.h
|
| 295 | + rts/ASANUtils.h
|
|
| 295 | 296 | rts/ExecPage.h
|
| 296 | 297 | rts/BlockSignals.h
|
| 297 | 298 | rts/Bytecodes.h
|
| ... | ... | @@ -241,6 +241,9 @@ tail_of (bdescr *bd) |
| 241 | 241 | STATIC_INLINE void
|
| 242 | 242 | initGroup(bdescr *head)
|
| 243 | 243 | {
|
| 244 | + __asan_unpoison_memory_region(head,
|
|
| 245 | + stg_min((W_)head->blocks, (W_)BLOCKS_PER_MBLOCK) * sizeof(bdescr));
|
|
| 246 | + |
|
| 244 | 247 | head->free = head->start;
|
| 245 | 248 | head->link = NULL;
|
| 246 | 249 | |
| ... | ... | @@ -261,6 +264,8 @@ initGroup(bdescr *head) |
| 261 | 264 | head[i].flags = 0;
|
| 262 | 265 | }
|
| 263 | 266 | #endif
|
| 267 | + |
|
| 268 | + __asan_unpoison_memory_region(head->start, (W_)head->blocks * BLOCK_SIZE);
|
|
| 264 | 269 | }
|
| 265 | 270 | |
| 266 | 271 | #if SIZEOF_VOID_P == SIZEOF_LONG
|
| ... | ... | @@ -308,6 +313,7 @@ setup_tail (bdescr *bd) |
| 308 | 313 | bdescr *tail;
|
| 309 | 314 | tail = tail_of(bd);
|
| 310 | 315 | if (tail != bd) {
|
| 316 | + __asan_unpoison_memory_region(tail, sizeof(bdescr));
|
|
| 311 | 317 | tail->blocks = 0;
|
| 312 | 318 | tail->free = 0;
|
| 313 | 319 | tail->link = bd;
|
| ... | ... | @@ -325,6 +331,7 @@ split_free_block (bdescr *bd, uint32_t node, W_ n, uint32_t ln /* log_2_ceil(n) |
| 325 | 331 | ASSERT(bd->blocks > n);
|
| 326 | 332 | dbl_link_remove(bd, &free_list[node][ln]);
|
| 327 | 333 | fg = bd + bd->blocks - n; // take n blocks off the end
|
| 334 | + __asan_unpoison_memory_region(fg, sizeof(bdescr));
|
|
| 328 | 335 | fg->blocks = n;
|
| 329 | 336 | bd->blocks -= n;
|
| 330 | 337 | setup_tail(bd);
|
| ... | ... | @@ -474,6 +481,8 @@ alloc_mega_group (uint32_t node, StgWord mblocks) |
| 474 | 481 | bd = alloc_mega_group_from_free_list(&deferred_free_mblock_list[node], n, &best);
|
| 475 | 482 | if(bd)
|
| 476 | 483 | {
|
| 484 | + __asan_unpoison_memory_region(MBLOCK_ROUND_DOWN(bd), FIRST_BLOCK_OFF);
|
|
| 485 | + __asan_unpoison_memory_region(bd->start, (W_)bd->blocks * BLOCK_SIZE);
|
|
| 477 | 486 | return bd;
|
| 478 | 487 | }
|
| 479 | 488 | else if(!best)
|
| ... | ... | @@ -490,6 +499,8 @@ alloc_mega_group (uint32_t node, StgWord mblocks) |
| 490 | 499 | |
| 491 | 500 | if (bd)
|
| 492 | 501 | {
|
| 502 | + __asan_unpoison_memory_region(MBLOCK_ROUND_DOWN(bd), FIRST_BLOCK_OFF);
|
|
| 503 | + __asan_unpoison_memory_region(bd->start, (W_)bd->blocks * BLOCK_SIZE);
|
|
| 493 | 504 | return bd;
|
| 494 | 505 | }
|
| 495 | 506 | else if (best)
|
| ... | ... | @@ -500,6 +511,7 @@ alloc_mega_group (uint32_t node, StgWord mblocks) |
| 500 | 511 | (best_mblocks-mblocks)*MBLOCK_SIZE);
|
| 501 | 512 | |
| 502 | 513 | best->blocks = MBLOCK_GROUP_BLOCKS(best_mblocks - mblocks);
|
| 514 | + __asan_unpoison_memory_region(MBLOCK_ROUND_DOWN(bd), mblocks * MBLOCK_SIZE);
|
|
| 503 | 515 | initMBlock(MBLOCK_ROUND_DOWN(bd), node);
|
| 504 | 516 | }
|
| 505 | 517 | else
|
| ... | ... | @@ -880,6 +892,11 @@ free_mega_group (bdescr *mg) |
| 880 | 892 | |
| 881 | 893 | IF_DEBUG(sanity, checkFreeListSanity());
|
| 882 | 894 | }
|
| 895 | + |
|
| 896 | + __asan_poison_memory_region(mg->start, (W_)mg->blocks * BLOCK_SIZE);
|
|
| 897 | + // Only the head bdescr of a free mega group carries meaning; poison the
|
|
| 898 | + // rest of the first mblock's descriptor area.
|
|
| 899 | + __asan_poison_memory_region(mg + 1, ((W_)BLOCKS_PER_MBLOCK - 1) * sizeof(bdescr));
|
|
| 883 | 900 | }
|
| 884 | 901 | |
| 885 | 902 | static void
|
| ... | ... | @@ -927,6 +944,9 @@ free_deferred_mega_groups (uint32_t node) |
| 927 | 944 | // coalesce forwards
|
| 928 | 945 | coalesce_mblocks(mg);
|
| 929 | 946 | |
| 947 | + __asan_poison_memory_region(mg->start, (W_)mg->blocks * BLOCK_SIZE);
|
|
| 948 | + __asan_poison_memory_region(mg + 1, ((W_)BLOCKS_PER_MBLOCK - 1) * sizeof(bdescr));
|
|
| 949 | + |
|
| 930 | 950 | // initialize search for next round
|
| 931 | 951 | prev = mg;
|
| 932 | 952 | bd = prev->link;
|
| ... | ... | @@ -979,7 +999,9 @@ freeGroup(bdescr *p) |
| 979 | 999 | RELAXED_STORE(&p->gen, NULL);
|
| 980 | 1000 | RELAXED_STORE(&p->gen_no, 0);
|
| 981 | 1001 | /* fill the block group with garbage if sanity checking is on */
|
| 982 | - IF_DEBUG(zero_on_gc, memset(p->start, 0xaa, (W_)p->blocks * BLOCK_SIZE));
|
|
| 1002 | + IF_DEBUG(zero_on_gc,
|
|
| 1003 | + __asan_unpoison_memory_region(p->start, (W_)p->blocks * BLOCK_SIZE);
|
|
| 1004 | + memset(p->start, 0xaa, (W_)p->blocks * BLOCK_SIZE));
|
|
| 983 | 1005 | |
| 984 | 1006 | if (p->blocks == 0) barf("freeGroup: block size is zero");
|
| 985 | 1007 | |
| ... | ... | @@ -1050,6 +1072,13 @@ freeGroup(bdescr *p) |
| 1050 | 1072 | setup_tail(p);
|
| 1051 | 1073 | free_list_insert(node,p);
|
| 1052 | 1074 | |
| 1075 | + __asan_poison_memory_region(p->start, (W_)p->blocks * BLOCK_SIZE);
|
|
| 1076 | + // Only the head and tail bdescrs of a free group carry meaning; poison the
|
|
| 1077 | + // interior ones to catch stale Bdescr() lookups through dangling pointers.
|
|
| 1078 | + if (p->blocks > 2) {
|
|
| 1079 | + __asan_poison_memory_region(p + 1, ((W_)p->blocks - 2) * sizeof(bdescr));
|
|
| 1080 | + }
|
|
| 1081 | + |
|
| 1053 | 1082 | IF_DEBUG(sanity, checkFreeListSanity());
|
| 1054 | 1083 | }
|
| 1055 | 1084 | |
| ... | ... | @@ -1421,6 +1450,7 @@ reportUnmarkedBlocks (void) |
| 1421 | 1450 | debugBelch("Unreachable blocks:\n");
|
| 1422 | 1451 | for (mblock = getFirstMBlock(&state); mblock != NULL;
|
| 1423 | 1452 | mblock = getNextMBlock(&state, mblock)) {
|
| 1453 | + __asan_unpoison_memory_region(mblock, FIRST_BLOCK_OFF);
|
|
| 1424 | 1454 | for (bd = FIRST_BDESCR(mblock); bd <= LAST_BDESCR(mblock); ) {
|
| 1425 | 1455 | if (!(bd->flags & BF_KNOWN) && bd->free != (P_)-1) {
|
| 1426 | 1456 | debugBelch(" %p\n",bd);
|
| ... | ... | @@ -348,6 +348,7 @@ alloc_todo_block (gen_workspace *ws, uint32_t size) |
| 348 | 348 | } else {
|
| 349 | 349 | if (gct->free_blocks) {
|
| 350 | 350 | bd = gct->free_blocks;
|
| 351 | + __asan_unpoison_memory_region(bd->start, (W_)bd->blocks * BLOCK_SIZE);
|
|
| 351 | 352 | gct->free_blocks = bd->link;
|
| 352 | 353 | } else {
|
| 353 | 354 | // We allocate in chunks of at most 16 blocks, use one
|
| ... | ... | @@ -357,6 +358,9 @@ alloc_todo_block (gen_workspace *ws, uint32_t size) |
| 357 | 358 | StgWord n_blocks = stg_min(chunk_size, 1 << (MBLOCK_SHIFT - BLOCK_SHIFT - 1));
|
| 358 | 359 | allocBlocks_sync(n_blocks, &bd);
|
| 359 | 360 | gct->free_blocks = bd->link;
|
| 361 | + for (bdescr *bd = gct->free_blocks; bd; bd = bd->link) {
|
|
| 362 | + __asan_poison_memory_region(bd->start, (W_)bd->blocks * BLOCK_SIZE);
|
|
| 363 | + }
|
|
| 360 | 364 | }
|
| 361 | 365 | }
|
| 362 | 366 | initBdescr(bd, ws->gen, ws->gen->to);
|
| ... | ... | @@ -641,6 +641,8 @@ getMBlocks(uint32_t n) |
| 641 | 641 | |
| 642 | 642 | ret = getCommittedMBlocks(n);
|
| 643 | 643 | |
| 644 | + __asan_unpoison_memory_region(ret, (W_)n * MBLOCK_SIZE);
|
|
| 645 | + |
|
| 644 | 646 | debugTrace(DEBUG_gc, "allocated %d megablock(s) at %p",n,ret);
|
| 645 | 647 | |
| 646 | 648 | mblocks_allocated += n;
|
| ... | ... | @@ -673,6 +675,8 @@ freeMBlocks(void *addr, uint32_t n) |
| 673 | 675 | |
| 674 | 676 | mblocks_allocated -= n;
|
| 675 | 677 | |
| 678 | + __asan_poison_memory_region(addr, (W_)n * MBLOCK_SIZE);
|
|
| 679 | + |
|
| 676 | 680 | decommitMBlocks(addr, n);
|
| 677 | 681 | }
|
| 678 | 682 |
| ... | ... | @@ -597,6 +597,8 @@ static void nonmovingExitConcurrentWorker(void); |
| 597 | 597 | void nonmovingPushFreeSegment(struct NonmovingSegment *seg)
|
| 598 | 598 | {
|
| 599 | 599 | SET_SEGMENT_STATE(seg, FREE);
|
| 600 | + __asan_poison_memory_region(seg->bitmap,
|
|
| 601 | + (uintptr_t)seg + NONMOVING_SEGMENT_SIZE - (uintptr_t)seg->bitmap);
|
|
| 600 | 602 | while (true) {
|
| 601 | 603 | struct NonmovingSegment *old = nonmovingHeap.free;
|
| 602 | 604 | seg->link = old;
|
| ... | ... | @@ -118,6 +118,8 @@ static void nonmovingClearBitmap(struct NonmovingSegment *seg) |
| 118 | 118 | static void nonmovingInitSegment(struct NonmovingSegment *seg, uint16_t allocator_idx)
|
| 119 | 119 | {
|
| 120 | 120 | bdescr *bd = Bdescr((P_) seg);
|
| 121 | + __asan_unpoison_memory_region(seg->bitmap,
|
|
| 122 | + (uintptr_t)seg + NONMOVING_SEGMENT_SIZE - (uintptr_t)seg->bitmap);
|
|
| 121 | 123 | seg->link = NULL;
|
| 122 | 124 | seg->todo_link = NULL;
|
| 123 | 125 | seg->next_free = 0;
|
| ... | ... | @@ -126,6 +128,8 @@ static void nonmovingInitSegment(struct NonmovingSegment *seg, uint16_t allocato |
| 126 | 128 | bd->nonmoving_segment.next_free_snap = 0;
|
| 127 | 129 | bd->u.scan = nonmovingSegmentGetBlock(seg, 0);
|
| 128 | 130 | nonmovingClearBitmap(seg);
|
| 131 | + __asan_poison_memory_region(bd->u.scan,
|
|
| 132 | + (uintptr_t)seg + NONMOVING_SEGMENT_SIZE - (uintptr_t)bd->u.scan);
|
|
| 129 | 133 | }
|
| 130 | 134 | |
| 131 | 135 | /* Initialize a new capability. Must hold SM_LOCK. */
|
| ... | ... | @@ -229,6 +233,7 @@ static void *nonmovingAllocate_(enum AllocLockMode mode, Capability *cap, StgWor |
| 229 | 233 | unsigned int block_count = nonmovingSegmentBlockCount(current);
|
| 230 | 234 | void *ret = nonmovingSegmentGetBlock_(current, block_size, block_count, current->next_free);
|
| 231 | 235 | ASSERT(GET_CLOSURE_TAG(ret) == 0); // check alignment
|
| 236 | + __asan_unpoison_memory_region(ret, block_size);
|
|
| 232 | 237 | |
| 233 | 238 | // Advance the current segment's next_free or allocate a new segment if full
|
| 234 | 239 | bool full = advance_next_free(current, block_count);
|
| ... | ... | @@ -33,6 +33,7 @@ nonmovingSweepSegment(struct NonmovingSegment *seg) |
| 33 | 33 | {
|
| 34 | 34 | ASSERT_SEGMENT_STATE(seg, FILLED_SWEEPING);
|
| 35 | 35 | const nonmoving_block_idx blk_cnt = nonmovingSegmentBlockCount(seg);
|
| 36 | + const uint16_t blk_size = nonmovingSegmentBlockSize(seg);
|
|
| 36 | 37 | bool found_free = false;
|
| 37 | 38 | bool found_live = false;
|
| 38 | 39 | |
| ... | ... | @@ -42,6 +43,8 @@ nonmovingSweepSegment(struct NonmovingSegment *seg) |
| 42 | 43 | found_live = true;
|
| 43 | 44 | } else {
|
| 44 | 45 | seg->bitmap[i] = 0;
|
| 46 | + __asan_poison_memory_region(
|
|
| 47 | + nonmovingSegmentGetBlock_(seg, blk_size, blk_cnt, i), blk_size);
|
|
| 45 | 48 | if (!found_free) {
|
| 46 | 49 | // This is the first free block we've found; set next_free,
|
| 47 | 50 | // next_free_snap, and the scan pointer.
|
| ... | ... | @@ -57,6 +60,8 @@ nonmovingSweepSegment(struct NonmovingSegment *seg) |
| 57 | 60 | for (; i < nonmovingSegmentBlockCount(seg); ++i) {
|
| 58 | 61 | if (seg->bitmap[i] != nonmovingMarkEpoch) {
|
| 59 | 62 | seg->bitmap[i] = 0;
|
| 63 | + __asan_poison_memory_region(
|
|
| 64 | + nonmovingSegmentGetBlock_(seg, blk_size, blk_cnt, i), blk_size);
|
|
| 60 | 65 | }
|
| 61 | 66 | }
|
| 62 | 67 | return SEGMENT_PARTIAL;
|
| ... | ... | @@ -113,7 +118,9 @@ void |
| 113 | 118 | nonmovingClearSegment(struct NonmovingSegment* seg)
|
| 114 | 119 | {
|
| 115 | 120 | size_t end = ((size_t)seg) + NONMOVING_SEGMENT_SIZE;
|
| 121 | + __asan_unpoison_memory_region(&seg->bitmap, end - (size_t)&seg->bitmap);
|
|
| 116 | 122 | memset(&seg->bitmap, 0, end - (size_t)&seg->bitmap);
|
| 123 | + __asan_poison_memory_region(&seg->bitmap, end - (size_t)&seg->bitmap);
|
|
| 117 | 124 | }
|
| 118 | 125 | |
| 119 | 126 | void
|
| ... | ... | @@ -124,7 +131,18 @@ nonmovingClearSegmentFreeBlocks(struct NonmovingSegment* seg) |
| 124 | 131 | // N.B. nonmovingSweepSegment helpfully clears the bitmap entries of
|
| 125 | 132 | // dead blocks
|
| 126 | 133 | if (nonmovingGetMark(seg, p_idx) == 0) {
|
| 127 | - memset(nonmovingSegmentGetBlock(seg, p_idx), 0, block_size);
|
|
| 134 | + void *blk = nonmovingSegmentGetBlock(seg, p_idx);
|
|
| 135 | + if (p_idx >= seg->next_free) {
|
|
| 136 | + // Free block: it is poisoned, so unpoison for the memset and
|
|
| 137 | + // re-poison afterwards. Unmarked blocks below next_free were
|
|
| 138 | + // allocated since the last sweep and are live; leave those
|
|
| 139 | + // unpoisoned.
|
|
| 140 | + __asan_unpoison_memory_region(blk, block_size);
|
|
| 141 | + memset(blk, 0, block_size);
|
|
| 142 | + __asan_poison_memory_region(blk, block_size);
|
|
| 143 | + } else {
|
|
| 144 | + memset(blk, 0, block_size);
|
|
| 145 | + }
|
|
| 128 | 146 | }
|
| 129 | 147 | }
|
| 130 | 148 | }
|
| ... | ... | @@ -1242,6 +1242,10 @@ start_new_pinned_block(Capability *cap) |
| 1242 | 1242 | ACQUIRE_SM_LOCK;
|
| 1243 | 1243 | bd = allocNursery(cap->node, NULL, PINNED_EMPTY_SIZE);
|
| 1244 | 1244 | RELEASE_SM_LOCK;
|
| 1245 | + |
|
| 1246 | + for (bdescr *pbd = bd; pbd; pbd = pbd->link) {
|
|
| 1247 | + __asan_poison_memory_region(pbd->start, (W_)pbd->blocks * BLOCK_SIZE);
|
|
| 1248 | + }
|
|
| 1245 | 1249 | }
|
| 1246 | 1250 | |
| 1247 | 1251 | // Bump up the nursery pointer to avoid the pathological situation
|
| ... | ... | @@ -1267,6 +1271,7 @@ start_new_pinned_block(Capability *cap) |
| 1267 | 1271 | }
|
| 1268 | 1272 | |
| 1269 | 1273 | cap->pinned_object_empty = bd->link;
|
| 1274 | + __asan_unpoison_memory_region(bd->start, (W_)bd->blocks * BLOCK_SIZE);
|
|
| 1270 | 1275 | newNurseryBlock(bd);
|
| 1271 | 1276 | if (bd->link != NULL) {
|
| 1272 | 1277 | bd->link->u.back = cap->pinned_object_empty;
|