From a5fa4dba6e2e01c4e8c4571301048c392facaed5 Mon Sep 17 00:00:00 2001 From: PiJoules Date: Fri, 27 Mar 2026 16:16:52 -0700 Subject: [PATCH] [compiler-rt] Add interceptors for free_[aligned_]sized for asan+hwasan (#189109) --- compiler-rt/lib/asan/asan_allocator.cpp | 13 ++++++++ compiler-rt/lib/asan/asan_allocator.h | 3 ++ compiler-rt/lib/asan/asan_malloc_linux.cpp | 22 +++++++++++++ .../hwasan/hwasan_allocation_functions.cpp | 32 +++++++++++++++++++ .../TestCases/Linux/free_aligned_sized.c | 2 +- .../TestCases/Linux/free_sized.c | 2 +- 6 files changed, 72 insertions(+), 2 deletions(-) diff --git a/compiler-rt/lib/asan/asan_allocator.cpp b/compiler-rt/lib/asan/asan_allocator.cpp index 59aeec6a6ae6..f9ec69257ee0 100644 --- a/compiler-rt/lib/asan/asan_allocator.cpp +++ b/compiler-rt/lib/asan/asan_allocator.cpp @@ -1043,6 +1043,19 @@ void asan_free(void *ptr, BufferedStackTrace *stack) { instance.Deallocate(ptr, 0, 0, stack, FROM_MALLOC); } +// TODO: Both the size and alignment arguments of Allocator::Deallocate +// are actually unused when the alloc type is FROM_MALLOC. We should look +// into why this is the case, but for now passing the arguments like so +// is the correct thing to do. +void asan_free_sized(void* ptr, uptr size, BufferedStackTrace* stack) { + instance.Deallocate(ptr, size, /*delete_alignment=*/0, stack, FROM_MALLOC); +} + +void asan_free_aligned_sized(void* ptr, uptr alignment, uptr size, + BufferedStackTrace* stack) { + instance.Deallocate(ptr, size, alignment, stack, FROM_MALLOC); +} + void *asan_malloc(uptr size, BufferedStackTrace *stack) { return SetErrnoOnNull(instance.Allocate(size, 8, stack, FROM_MALLOC, true)); } diff --git a/compiler-rt/lib/asan/asan_allocator.h b/compiler-rt/lib/asan/asan_allocator.h index 8521e8d068db..a02d1434a273 100644 --- a/compiler-rt/lib/asan/asan_allocator.h +++ b/compiler-rt/lib/asan/asan_allocator.h @@ -277,6 +277,9 @@ struct AsanThreadLocalMallocStorage { void *asan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack); void asan_free(void *ptr, BufferedStackTrace *stack); +void asan_free_sized(void* ptr, uptr size, BufferedStackTrace* stack); +void asan_free_aligned_sized(void* ptr, uptr alignment, uptr size, + BufferedStackTrace* stack); void *asan_malloc(uptr size, BufferedStackTrace *stack); void *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack); diff --git a/compiler-rt/lib/asan/asan_malloc_linux.cpp b/compiler-rt/lib/asan/asan_malloc_linux.cpp index a1b10a5fb855..35bf55da1c66 100644 --- a/compiler-rt/lib/asan/asan_malloc_linux.cpp +++ b/compiler-rt/lib/asan/asan_malloc_linux.cpp @@ -61,6 +61,28 @@ INTERCEPTOR(void, cfree, void *ptr) { } #endif // SANITIZER_INTERCEPT_CFREE +# if SANITIZER_INTERCEPT_FREE_SIZED +INTERCEPTOR(void, free_sized, void* ptr, uptr size) { + if (UNLIKELY(!ptr)) + return; + if (DlsymAlloc::PointerIsMine(ptr)) + return DlsymAlloc::Free(ptr); + GET_STACK_TRACE_FREE; + asan_free_sized(ptr, size, &stack); +} +# endif // SANITIZER_INTERCEPT_FREE_SIZED + +# if SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED +INTERCEPTOR(void, free_aligned_sized, void* ptr, uptr alignment, uptr size) { + if (UNLIKELY(!ptr)) + return; + if (DlsymAlloc::PointerIsMine(ptr)) + return DlsymAlloc::Free(ptr); + GET_STACK_TRACE_FREE; + asan_free_aligned_sized(ptr, alignment, size, &stack); +} +# endif // SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED + # if SANITIZER_AIX // Unlike malloc, vec_malloc must return memory aligned to 16 bytes. INTERCEPTOR(void*, vec_malloc, uptr size) { diff --git a/compiler-rt/lib/hwasan/hwasan_allocation_functions.cpp b/compiler-rt/lib/hwasan/hwasan_allocation_functions.cpp index 25ca0a3b0b68..ee2794f4cfbf 100644 --- a/compiler-rt/lib/hwasan/hwasan_allocation_functions.cpp +++ b/compiler-rt/lib/hwasan/hwasan_allocation_functions.cpp @@ -17,6 +17,7 @@ #include "sanitizer_common/sanitizer_allocator_dlsym.h" #include "sanitizer_common/sanitizer_allocator_interface.h" #include "sanitizer_common/sanitizer_mallinfo.h" +#include "sanitizer_common/sanitizer_platform_interceptors.h" using namespace __hwasan; @@ -96,6 +97,30 @@ void __sanitizer_cfree(void *ptr) { hwasan_free(ptr, &stack); } +#if SANITIZER_INTERCEPT_FREE_SIZED +SANITIZER_INTERFACE_ATTRIBUTE +void __sanitizer_free_sized(void* ptr, uptr size) { + if (!ptr) + return; + if (DlsymAlloc::PointerIsMine(ptr)) + return DlsymAlloc::Free(ptr); + GET_MALLOC_STACK_TRACE; + hwasan_free(ptr, &stack); +} +#endif + +#if SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED +SANITIZER_INTERFACE_ATTRIBUTE +void __sanitizer_free_aligned_sized(void* ptr, uptr alignment, uptr size) { + if (!ptr) + return; + if (DlsymAlloc::PointerIsMine(ptr)) + return DlsymAlloc::Free(ptr); + GET_MALLOC_STACK_TRACE; + hwasan_free(ptr, &stack); +} +#endif + SANITIZER_INTERFACE_ATTRIBUTE uptr __sanitizer_malloc_usable_size(const void *ptr) { return __sanitizer_get_allocated_size(ptr); @@ -170,6 +195,13 @@ INTERCEPTOR_ALIAS(void *, aligned_alloc, SIZE_T alignment, SIZE_T size); INTERCEPTOR_ALIAS(void *, __libc_memalign, SIZE_T alignment, SIZE_T size); INTERCEPTOR_ALIAS(void *, valloc, SIZE_T size); INTERCEPTOR_ALIAS(void, free, void *ptr); +# if SANITIZER_INTERCEPT_FREE_SIZED +INTERCEPTOR_ALIAS(void, free_sized, void* ptr, SIZE_T size); +# endif +# if SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED +INTERCEPTOR_ALIAS(void, free_aligned_sized, void* ptr, SIZE_T alignment, + SIZE_T size); +# endif INTERCEPTOR_ALIAS(uptr, malloc_usable_size, const void *ptr); INTERCEPTOR_ALIAS(void *, calloc, SIZE_T nmemb, SIZE_T size); INTERCEPTOR_ALIAS(void *, realloc, void *ptr, SIZE_T size); diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/free_aligned_sized.c b/compiler-rt/test/sanitizer_common/TestCases/Linux/free_aligned_sized.c index 15b1a43f596e..7c52af1e9dbd 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/Linux/free_aligned_sized.c +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/free_aligned_sized.c @@ -1,5 +1,5 @@ // RUN: %clang -std=c23 -O0 %s -o %t && %run %t -// UNSUPPORTED: asan, hwasan, ubsan +// UNSUPPORTED: ubsan #include #include diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/free_sized.c b/compiler-rt/test/sanitizer_common/TestCases/Linux/free_sized.c index d8ec1e8b364b..3dde1277496a 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/Linux/free_sized.c +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/free_sized.c @@ -1,5 +1,5 @@ // RUN: %clang -std=c23 -O0 %s -o %t && %run %t -// UNSUPPORTED: asan, hwasan, ubsan +// UNSUPPORTED: ubsan #include #include