diff --git a/compiler-rt/lib/lsan/lsan_allocator.cpp b/compiler-rt/lib/lsan/lsan_allocator.cpp --- a/compiler-rt/lib/lsan/lsan_allocator.cpp +++ b/compiler-rt/lib/lsan/lsan_allocator.cpp @@ -123,14 +123,18 @@ void *Reallocate(const StackTrace &stack, void *p, uptr new_size, uptr alignment) { - RegisterDeallocation(p); if (new_size > max_malloc_size) { - allocator.Deallocate(GetAllocatorCache(), p); - return ReportAllocationSizeTooBig(new_size, stack); + ReportAllocationSizeTooBig(new_size, stack); + return nullptr; } - p = allocator.Reallocate(GetAllocatorCache(), p, new_size, alignment); - RegisterAllocation(stack, p, new_size); - return p; + RegisterDeallocation(p); + void *new_p = + allocator.Reallocate(GetAllocatorCache(), p, new_size, alignment); + if (new_p) + RegisterAllocation(stack, new_p, new_size); + else if (new_size != 0) + RegisterAllocation(stack, p, new_size); + return new_p; } void GetAllocatorCacheRange(uptr *begin, uptr *end) { diff --git a/compiler-rt/test/lsan/TestCases/realloc_too_big.c b/compiler-rt/test/lsan/TestCases/realloc_too_big.c new file mode 100644 --- /dev/null +++ b/compiler-rt/test/lsan/TestCases/realloc_too_big.c @@ -0,0 +1,18 @@ +// RUN: %clang_lsan %s -o %t +// RUN: %env_lsan_opts=allocator_may_return_null=1:max_allocation_size_mb=1:use_stacks=0 not %run %t 2>&1 | FileCheck %s + +#include +#include +#include + +// CHECK: {{Leak|Address}}Sanitizer failed to allocate 0x100001 bytes + +// CHECK: {{Leak|Address}}Sanitizer: detected memory leaks +// CHECK: {{Leak|Address}}Sanitizer: 9 byte(s) leaked in 1 allocation(s). + +int main() { + char *p = malloc(9); + fprintf(stderr, "nine: %p\n", p); + assert(realloc(p, 0x100001) == NULL); // 1MiB+1 + p = 0; +}