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 @@ -1111,19 +1111,17 @@ *end = *begin + sizeof(__asan::get_allocator()); } -uptr PointsIntoChunk(void* p) { +uptr PointsIntoChunk(void *p) { uptr addr = reinterpret_cast(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) { diff --git a/compiler-rt/test/asan/TestCases/redzone_noleak.cpp b/compiler-rt/test/asan/TestCases/redzone_noleak.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/redzone_noleak.cpp @@ -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 +#include +#include + +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; +}