diff --git a/compiler-rt/lib/lsan/lsan_allocator.cpp b/compiler-rt/lib/lsan/lsan_allocator.cpp index 493bf5f9efc57..a436d9c07ac6c 100644 --- a/compiler-rt/lib/lsan/lsan_allocator.cpp +++ b/compiler-rt/lib/lsan/lsan_allocator.cpp @@ -220,6 +220,10 @@ void lsan_free(void *p) { Deallocate(p); } +void lsan_free_sized(void *p, uptr) { Deallocate(p); } + +void lsan_free_aligned_sized(void *p, uptr, uptr) { Deallocate(p); } + void *lsan_realloc(void *p, uptr size, const StackTrace &stack) { return SetErrnoOnNull(Reallocate(stack, p, size, 1)); } diff --git a/compiler-rt/lib/lsan/lsan_allocator.h b/compiler-rt/lib/lsan/lsan_allocator.h index 5eed0cbdb309b..2342f11fb5d0d 100644 --- a/compiler-rt/lib/lsan/lsan_allocator.h +++ b/compiler-rt/lib/lsan/lsan_allocator.h @@ -127,6 +127,8 @@ void *lsan_aligned_alloc(uptr alignment, uptr size, const StackTrace &stack); void *lsan_memalign(uptr alignment, uptr size, const StackTrace &stack); void *lsan_malloc(uptr size, const StackTrace &stack); void lsan_free(void *p); +void lsan_free_sized(void *p, uptr size); +void lsan_free_aligned_sized(void *p, uptr alignment, uptr size); void *lsan_realloc(void *p, uptr size, const StackTrace &stack); void *lsan_reallocarray(void *p, uptr nmemb, uptr size, const StackTrace &stack); diff --git a/compiler-rt/lib/lsan/lsan_interceptors.cpp b/compiler-rt/lib/lsan/lsan_interceptors.cpp index a8252cddacf25..6da9d0d9d24f8 100644 --- a/compiler-rt/lib/lsan/lsan_interceptors.cpp +++ b/compiler-rt/lib/lsan/lsan_interceptors.cpp @@ -84,6 +84,35 @@ INTERCEPTOR(void, free, void *p) { lsan_free(p); } +# if SANITIZER_INTERCEPT_FREE_SIZED +INTERCEPTOR(void, free_sized, void *p, uptr size) { + if (UNLIKELY(!p)) + return; + if (DlsymAlloc::PointerIsMine(p)) + return DlsymAlloc::Free(p); + ENSURE_LSAN_INITED; + lsan_free_sized(p, size); +} +# define LSAN_MAYBE_INTERCEPT_FREE_SIZED INTERCEPT_FUNCTION(free_sized) +# else +# define LSAN_MAYBE_INTERCEPT_FREE_SIZED +# endif + +# if SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED +INTERCEPTOR(void, free_aligned_sized, void *p, uptr alignment, uptr size) { + if (UNLIKELY(!p)) + return; + if (DlsymAlloc::PointerIsMine(p)) + return DlsymAlloc::Free(p); + ENSURE_LSAN_INITED; + lsan_free_aligned_sized(p, alignment, size); +} +# define LSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED \ + INTERCEPT_FUNCTION(free_aligned_sized) +# else +# define LSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED +# endif + INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { if (DlsymAlloc::Use()) return DlsymAlloc::Callocate(nmemb, size); @@ -547,6 +576,8 @@ void InitializeInterceptors() { INTERCEPT_FUNCTION(malloc); INTERCEPT_FUNCTION(free); + LSAN_MAYBE_INTERCEPT_FREE_SIZED; + LSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED; LSAN_MAYBE_INTERCEPT_CFREE; INTERCEPT_FUNCTION(calloc); INTERCEPT_FUNCTION(realloc); diff --git a/compiler-rt/lib/lsan/lsan_malloc_mac.cpp b/compiler-rt/lib/lsan/lsan_malloc_mac.cpp index 525c30272ccca..8a16c053da238 100644 --- a/compiler-rt/lib/lsan/lsan_malloc_mac.cpp +++ b/compiler-rt/lib/lsan/lsan_malloc_mac.cpp @@ -44,16 +44,19 @@ using namespace __lsan; void *p = lsan_valloc(size, stack) #define COMMON_MALLOC_FREE(ptr) \ lsan_free(ptr) -#define COMMON_MALLOC_SIZE(ptr) \ - uptr size = lsan_mz_size(ptr) -#define COMMON_MALLOC_FILL_STATS(zone, stats) -#define COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name) \ - (void)zone_name; \ - Report("mz_realloc(%p) -- attempting to realloc unallocated memory.\n", ptr); -#define COMMON_MALLOC_NAMESPACE __lsan -#define COMMON_MALLOC_HAS_ZONE_ENUMERATOR 0 -#define COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT 0 +# define COMMON_MALLOC_FREE_SIZED(ptr, size) lsan_free_sized(ptr, size) +# define COMMON_MALLOC_FREE_ALIGNED_SIZED(ptr, alignment, size) \ + lsan_free_aligned_sized(ptr, alignment, size) +# define COMMON_MALLOC_SIZE(ptr) uptr size = lsan_mz_size(ptr) +# define COMMON_MALLOC_FILL_STATS(zone, stats) +# define COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name) \ + (void)zone_name; \ + Report("mz_realloc(%p) -- attempting to realloc unallocated memory.\n", \ + ptr); +# define COMMON_MALLOC_NAMESPACE __lsan +# define COMMON_MALLOC_HAS_ZONE_ENUMERATOR 0 +# define COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT 0 -#include "sanitizer_common/sanitizer_malloc_mac.inc" +# include "sanitizer_common/sanitizer_malloc_mac.inc" #endif // SANITIZER_APPLE diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_malloc_mac.inc b/compiler-rt/lib/sanitizer_common/sanitizer_malloc_mac.inc index 6343eb284afbf..be27584f20535 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_malloc_mac.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_malloc_mac.inc @@ -144,6 +144,22 @@ INTERCEPTOR(void, free, void *ptr) { COMMON_MALLOC_FREE(ptr); } +#if SANITIZER_INTERCEPT_FREE_SIZED && defined(COMMON_MALLOC_FREE_SIZED) +INTERCEPTOR(void, free_sized, void *ptr, size_t size) { + COMMON_MALLOC_ENTER(); + COMMON_MALLOC_FREE_SIZED(ptr, size); +} +#endif + +#if SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED && \ + defined(COMMON_MALLOC_FREE_ALIGNED_SIZED) +INTERCEPTOR(void, free_aligned_sized, void *ptr, size_t alignment, + size_t size) { + COMMON_MALLOC_ENTER(); + COMMON_MALLOC_FREE_ALIGNED_SIZED(ptr, alignment, size); +} +#endif + INTERCEPTOR(void *, realloc, void *ptr, size_t size) { COMMON_MALLOC_ENTER(); COMMON_MALLOC_REALLOC(ptr, size); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h index ccc808b60ca75..29987decdff45 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -663,6 +663,17 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment, #define SANITIZER_INTERCEPT_GETSERVBYNAME_R SI_GLIBC #define SANITIZER_INTERCEPT_GETSERVBYPORT_R SI_GLIBC +// Until free_sized and free_aligned_sized are more generally available, +// we can only unconditionally intercept on ELF-based platforms where it +// is okay to have undefined weak symbols. +#ifdef __ELF__ +# define SANITIZER_INTERCEPT_FREE_SIZED 1 +# define SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED 1 +#else +# define SANITIZER_INTERCEPT_FREE_SIZED 0 +# define SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED 0 +#endif + // This macro gives a way for downstream users to override the above // interceptor macros irrespective of the platform they are on. They have // to do two things: 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 f4c6c0f973bdb..e9cb6f20c5ead 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, rtsan, tsan, msan, lsan, ubsan +// UNSUPPORTED: asan, hwasan, rtsan, tsan, msan, 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 0ee2289684d0a..8cdf3216e528a 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, rtsan, tsan, msan, lsan, ubsan +// UNSUPPORTED: asan, hwasan, rtsan, tsan, msan, ubsan #include #include