[Asan] Fix false leak report

If user thread is in the allocator, the allocator
may have no pointer into future user's part of
the allocated block. AddrIsInside ignores such
pointers and lsan reports a false memory leak.

Reviewed By: morehouse

Differential Revision: https://reviews.llvm.org/D87552
This commit is contained in:
Vitaly Buka 2020-09-14 13:32:14 -07:00
parent c2590de30d
commit 9d01612db4
2 changed files with 34 additions and 8 deletions

View File

@ -1111,19 +1111,17 @@ void GetAllocatorGlobalRange(uptr *begin, uptr *end) {
*end = *begin + sizeof(__asan::get_allocator());
}
uptr PointsIntoChunk(void* p) {
uptr PointsIntoChunk(void *p) {
uptr addr = reinterpret_cast<uptr>(p);
__asan::AsanChunk *m = __asan::instance.GetAsanChunkByAddrFastLocked(addr);
if (!m || atomic_load(&m->chunk_state, memory_order_acquire) !=
__asan::CHUNK_ALLOCATED)
return 0;
uptr chunk = m->Beg();
if (m->AddrIsInside(addr, /*locked_version=*/true))
return chunk;
if (IsSpecialCaseOfOperatorNew0(chunk, m->UsedSize(/*locked_version*/ true),
addr))
return chunk;
return 0;
// AsanChunk presence means that we point into some block from underlying
// allocators. Don't check whether p points into user memory, since until
// the return from AsanAllocator::Allocator we may have no such
// pointer anywhere. But we must already have a pointer to GetBlockBegin().
return m->Beg();
}
uptr GetUserBegin(uptr chunk) {

View File

@ -0,0 +1,28 @@
// Test whether pointers into left redzone count memory are reachable.
// If user thread is inside asan allocator code then we may have no
// pointers into user part of memory yet. However we should have a pointer
// into the allocated memory chunk.
//
// RUN: %clangxx_asan %s -o %t
// RUN: %run %t 2>&1
#include <cstdlib>
#include <stdio.h>
#include <thread>
void *pointers[1000];
void **cur = pointers;
void leak(int n, int offset) {
printf("%d %d\n", n, offset);
for (int i = 0; i < 3; ++i)
*(cur++) = (new int[n]) + offset;
}
int main(int argc, char **argv) {
for (int n = 1; n < 10000000; n = n * 2) {
leak(n, 0);
leak(n, -1);
}
return 0;
}