Skip to content

Commit 08507d8

Browse files
committed
[Asan] Cleanup kAllocBegMagic setup
Make it atomic. Wrap it into class. Set it late after chunk is initialized. Reset it soon when the chunk is still valid. Depends on D87645. Reviewed By: morehouse Differential Revision: https://reviews.llvm.org/D87646
1 parent a61bb7f commit 08507d8

File tree

1 file changed

+39
-20
lines changed

1 file changed

+39
-20
lines changed

compiler-rt/lib/asan/asan_allocator.cpp

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ static void AtomicContextLoad(const volatile atomic_uint64_t *atomic_context,
8484
// ---------------------|
8585
// M -- magic value kAllocBegMagic
8686
// B -- address of ChunkHeader pointing to the first 'H'
87-
static const uptr kAllocBegMagic = 0xCC6E96B9;
8887

8988
class ChunkHeader {
9089
public:
@@ -161,13 +160,47 @@ class AsanChunk : public ChunkBase {
161160
uptr Beg() { return reinterpret_cast<uptr>(this) + kChunkHeaderSize; }
162161
};
163162

163+
class LargeChunkHeader {
164+
static constexpr uptr kAllocBegMagic = 0xCC6E96B9;
165+
atomic_uint64_t magic;
166+
AsanChunk *chunk_header;
167+
168+
public:
169+
AsanChunk *Get() {
170+
return atomic_load(&magic, memory_order_acquire) == kAllocBegMagic
171+
? chunk_header
172+
: reinterpret_cast<AsanChunk *>(this);
173+
}
174+
175+
void Set(AsanChunk *p) {
176+
if (p) {
177+
chunk_header = p;
178+
atomic_store(&magic, kAllocBegMagic, memory_order_release);
179+
return;
180+
}
181+
182+
u64 old = kAllocBegMagic;
183+
if (!atomic_compare_exchange_strong(&magic, &old, 0,
184+
memory_order_release)) {
185+
CHECK_EQ(old, kAllocBegMagic);
186+
}
187+
}
188+
};
189+
164190
struct QuarantineCallback {
165191
QuarantineCallback(AllocatorCache *cache, BufferedStackTrace *stack)
166192
: cache_(cache),
167193
stack_(stack) {
168194
}
169195

170196
void Recycle(AsanChunk *m) {
197+
void *p = get_allocator().GetBlockBegin(m);
198+
if (p != m) {
199+
// Clear the magic value, as allocator internals may overwrite the
200+
// contents of deallocated chunk, confusing GetAsanChunk lookup.
201+
reinterpret_cast<LargeChunkHeader *>(p)->Set(nullptr);
202+
}
203+
171204
u8 old_chunk_state = CHUNK_QUARANTINE;
172205
if (!atomic_compare_exchange_strong(&m->chunk_state, &old_chunk_state,
173206
CHUNK_INVALID, memory_order_acquire)) {
@@ -177,15 +210,6 @@ struct QuarantineCallback {
177210
PoisonShadow(m->Beg(),
178211
RoundUpTo(m->UsedSize(), SHADOW_GRANULARITY),
179212
kAsanHeapLeftRedzoneMagic);
180-
void *p = get_allocator().GetBlockBegin(m);
181-
if (p != m) {
182-
uptr *alloc_magic = reinterpret_cast<uptr *>(p);
183-
CHECK_EQ(alloc_magic[0], kAllocBegMagic);
184-
// Clear the magic value, as allocator internals may overwrite the
185-
// contents of deallocated chunk, confusing GetAsanChunk lookup.
186-
alloc_magic[0] = 0;
187-
CHECK_EQ(alloc_magic[1], reinterpret_cast<uptr>(m));
188-
}
189213

190214
// Statistics.
191215
AsanStats &thread_stats = GetCurrentThreadStats();
@@ -541,11 +565,6 @@ struct Allocator {
541565
uptr chunk_beg = user_beg - kChunkHeaderSize;
542566
AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg);
543567
m->alloc_type = alloc_type;
544-
if (alloc_beg != chunk_beg) {
545-
CHECK_LE(alloc_beg + 2 * sizeof(uptr), chunk_beg);
546-
reinterpret_cast<uptr *>(alloc_beg)[0] = kAllocBegMagic;
547-
reinterpret_cast<uptr *>(alloc_beg)[1] = chunk_beg;
548-
}
549568
CHECK(size);
550569
m->SetUsedSize(size);
551570
if (using_primary_allocator) {
@@ -591,6 +610,10 @@ struct Allocator {
591610
#endif
592611
// Must be the last mutation of metadata in this function.
593612
atomic_store(&m->chunk_state, CHUNK_ALLOCATED, memory_order_release);
613+
if (alloc_beg != chunk_beg) {
614+
CHECK_LE(alloc_beg + sizeof(LargeChunkHeader), chunk_beg);
615+
reinterpret_cast<LargeChunkHeader *>(alloc_beg)->Set(m);
616+
}
594617
ASAN_MALLOC_HOOK(res, size);
595618
return res;
596619
}
@@ -763,11 +786,7 @@ struct Allocator {
763786
uptr *meta = reinterpret_cast<uptr *>(allocator.GetMetaData(alloc_beg));
764787
p = reinterpret_cast<AsanChunk *>(meta[1]);
765788
} else {
766-
uptr *alloc_magic = reinterpret_cast<uptr *>(alloc_beg);
767-
if (alloc_magic[0] == kAllocBegMagic)
768-
p = reinterpret_cast<AsanChunk *>(alloc_magic[1]);
769-
else
770-
p = reinterpret_cast<AsanChunk *>(alloc_beg);
789+
p = reinterpret_cast<LargeChunkHeader *>(alloc_beg)->Get();
771790
}
772791
if (!p)
773792
return nullptr;

0 commit comments

Comments
 (0)