diff --git a/compiler-rt/lib/asan/asan_allocator.cpp b/compiler-rt/lib/asan/asan_allocator.cpp --- a/compiler-rt/lib/asan/asan_allocator.cpp +++ b/compiler-rt/lib/asan/asan_allocator.cpp @@ -316,9 +316,9 @@ // This could be a user-facing chunk (with redzones), or some internal // housekeeping chunk, like TransferBatch. Start by assuming the former. AsanChunk *ac = GetAsanChunk((void *)chunk); - uptr allocated_size = allocator.GetActuallyAllocatedSize((void *)ac); - if (atomic_load(&ac->chunk_state, memory_order_acquire) == - CHUNK_ALLOCATED) { + uptr allocated_size = allocator.GetActuallyAllocatedSize((void *)chunk); + if (ac && atomic_load(&ac->chunk_state, memory_order_acquire) == + CHUNK_ALLOCATED) { uptr beg = ac->Beg(); uptr end = ac->Beg() + ac->UsedSize(); uptr chunk_end = chunk + allocated_size; @@ -398,6 +398,10 @@ // We have an address between two chunks, and we want to report just one. AsanChunk *ChooseChunk(uptr addr, AsanChunk *left_chunk, AsanChunk *right_chunk) { + if (!left_chunk) + return right_chunk; + if (!right_chunk) + return left_chunk; // Prefer an allocated chunk over freed chunk and freed chunk // over available chunk. u8 left_state = atomic_load(&left_chunk->chunk_state, memory_order_relaxed); @@ -751,18 +755,22 @@ AsanChunk *GetAsanChunk(void *alloc_beg) { if (!alloc_beg) return nullptr; + AsanChunk *p = nullptr; if (!allocator.FromPrimary(alloc_beg)) { uptr *meta = reinterpret_cast(allocator.GetMetaData(alloc_beg)); - AsanChunk *m = reinterpret_cast(meta[1]); - return m; + p = reinterpret_cast(meta[1]); + } else { + uptr *alloc_magic = reinterpret_cast(alloc_beg); + if (alloc_magic[0] == kAllocBegMagic) + p = reinterpret_cast(alloc_magic[1]); + else + p = reinterpret_cast(alloc_beg); } - uptr *alloc_magic = reinterpret_cast(alloc_beg); - if (alloc_magic[0] == kAllocBegMagic) - return reinterpret_cast(alloc_magic[1]); - // FIXME: This is either valid small chunk with tiny redzone or invalid - // chunk which is beeing allocated/deallocated. The latter case should - // return nullptr like secondary allocator does. - return reinterpret_cast(alloc_beg); + if (!p) + return nullptr; + if (atomic_load(&p->chunk_state, memory_order_relaxed) == CHUNK_INVALID) + return nullptr; + return p; } AsanChunk *GetAsanChunkByAddr(uptr p) { @@ -788,9 +796,8 @@ AsanChunkView FindHeapChunkByAddress(uptr addr) { AsanChunk *m1 = GetAsanChunkByAddr(addr); - if (!m1) return AsanChunkView(m1); sptr offset = 0; - if (AsanChunkView(m1).AddrIsAtLeft(addr, 1, &offset)) { + if (!m1 || AsanChunkView(m1).AddrIsAtLeft(addr, 1, &offset)) { // The address is in the chunk's left redzone, so maybe it is actually // a right buffer overflow from the other chunk to the left. // Search a bit to the left to see if there is another chunk.