diff --git a/compiler-rt/include/sanitizer/asan_interface.h b/compiler-rt/include/sanitizer/asan_interface.h --- a/compiler-rt/include/sanitizer/asan_interface.h +++ b/compiler-rt/include/sanitizer/asan_interface.h @@ -315,6 +315,10 @@ /// functions like _exit() and execl(). void __asan_handle_no_return(void); +/// Update allocation stack trace for the given allocation to the current stack +/// trace. Returns 1 if successfull, 0 if not. +int __asan_update_allocation_context(void* addr); + #ifdef __cplusplus } // extern "C" #endif 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 @@ -399,6 +399,16 @@ return right_chunk; } + bool UpdateAllocationStack(uptr addr, BufferedStackTrace *stack) { + AsanChunk *m = GetAsanChunkByAddr(addr); + if (!m) return false; + if (m->chunk_state != CHUNK_ALLOCATED) return false; + if (m->Beg() != addr) return false; + atomic_store((atomic_uint32_t *)&m->alloc_context_id, StackDepotPut(*stack), + memory_order_relaxed); + return true; + } + // -------------------- Allocation/Deallocation routines --------------- void *Allocate(uptr size, uptr alignment, BufferedStackTrace *stack, AllocType alloc_type, bool can_fill) { @@ -1112,6 +1122,11 @@ instance.Purge(&stack); } +int __asan_update_allocation_context(void* addr) { + GET_STACK_TRACE_MALLOC; + return instance.UpdateAllocationStack((uptr)addr, &stack); +} + #if !SANITIZER_SUPPORTS_WEAK_HOOKS // Provide default (no-op) implementation of malloc hooks. SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_malloc_hook, diff --git a/compiler-rt/lib/asan/asan_interface.inc b/compiler-rt/lib/asan/asan_interface.inc --- a/compiler-rt/lib/asan/asan_interface.inc +++ b/compiler-rt/lib/asan/asan_interface.inc @@ -164,6 +164,7 @@ INTERFACE_FUNCTION(__sanitizer_unaligned_store16) INTERFACE_FUNCTION(__sanitizer_unaligned_store32) INTERFACE_FUNCTION(__sanitizer_unaligned_store64) +INTERFACE_FUNCTION(__asan_update_allocation_context) INTERFACE_WEAK_FUNCTION(__asan_default_options) INTERFACE_WEAK_FUNCTION(__asan_default_suppressions) INTERFACE_WEAK_FUNCTION(__asan_on_error) diff --git a/compiler-rt/lib/asan/asan_interface_internal.h b/compiler-rt/lib/asan/asan_interface_internal.h --- a/compiler-rt/lib/asan/asan_interface_internal.h +++ b/compiler-rt/lib/asan/asan_interface_internal.h @@ -251,6 +251,8 @@ const char* __asan_default_suppressions(); SANITIZER_INTERFACE_ATTRIBUTE void __asan_handle_vfork(void *sp); + + SANITIZER_INTERFACE_ATTRIBUTE int __asan_update_allocation_context(void* addr); } // extern "C" #endif // ASAN_INTERFACE_INTERNAL_H diff --git a/compiler-rt/test/asan/TestCases/asan_update_allocation.cpp b/compiler-rt/test/asan/TestCases/asan_update_allocation.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/asan_update_allocation.cpp @@ -0,0 +1,19 @@ +// RUN: %clangxx_asan -O0 -DSIZE=10 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK +// RUN: %clangxx_asan -O0 -DSIZE=10000000 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK +// REQUIRES: stable-runtime + +#include +#include + +void UPDATE(void *p) { + __asan_update_allocation_context(p); +} + +int main() { + char *x = (char*)malloc(SIZE * sizeof(char)); + UPDATE(x); + free(x); + return x[5]; + // CHECK: {{.*ERROR: AddressSanitizer: heap-use-after-free on address}} + // CHECK: UPDATE +}