Index: lib/asan/asan_allocator.cc =================================================================== --- lib/asan/asan_allocator.cc +++ lib/asan/asan_allocator.cc @@ -800,8 +800,13 @@ if (!p) return instance.Allocate(size, 8, stack, FROM_MALLOC, true); if (size == 0) { - instance.Deallocate(p, 0, stack, FROM_MALLOC); - return nullptr; + if (flags()->free_on_realloc_zero) { + instance.Deallocate(p, 0, stack, FROM_MALLOC); + return nullptr; + } else { + // Allocate a size of 1 if we shouldn't free() on Realloc to 0 + size = 1; + } } return instance.Reallocate(p, size, stack); } Index: lib/asan/asan_flags.inc =================================================================== --- lib/asan/asan_flags.inc +++ lib/asan/asan_flags.inc @@ -148,3 +148,6 @@ "(WARNING: USE AT YOUR OWN RISK!)") ASAN_FLAG(bool, use_odr_indicator, false, "Use special ODR indicator symbol for ODR violation detection") +ASAN_FLAG(bool, free_on_realloc_zero, true, + "realloc(p, 0) is equivalent to free(p). If set to false, realloc(p, " + "0) returns a pointer to an allocated space which can not be used.") Index: test/asan/TestCases/realloc.cc =================================================================== --- /dev/null +++ test/asan/TestCases/realloc.cc @@ -0,0 +1,20 @@ +// RUN: %clangxx_asan -O0 %s -o %t +// Default is true (free on realloc to 0 size) +// RUN: %run %t 2>&1 | FileCheck %s +// RUN: %env_asan_opts=free_on_realloc_zero=true %run %t 2>&1 | FileCheck %s +// RUN: %env_asan_opts=free_on_realloc_zero=false %run %t 2>&1 | FileCheck %s -check-prefix=NO-FREE -allow-empty + +#include +#include + +int main(int argc, char **argv) { + void *p = malloc(argc); + p = realloc(p, 0); + if (p) + // NO-FREE: Allocated something on realloc(p, 0) + fprintf(stderr, "Allocated something on realloc(p, 0)\n"); + else + // CHECK: realloc(p, 0) returned nullptr + fprintf(stderr, "realloc(p, 0) returned nullptr\n"); + free(p); +}