[compiler-rt] lsan: Support free_sized and free_aligned_sized from C23 (PR #144604)
Justin King via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 17 14:09:41 PDT 2025
https://github.com/jcking created https://github.com/llvm/llvm-project/pull/144604
Adds support to LSan for `free_sized` and `free_aligned_sized` from C23.
Other sanitizers will be handled with their own separate PRs.
For https://github.com/llvm/llvm-project/issues/144435
This is attempt number 2.
>From 232a47f0323579f97f82903a8e4cf951d8096207 Mon Sep 17 00:00:00 2001
From: Justin King <jcking at google.com>
Date: Tue, 17 Jun 2025 14:06:06 -0700
Subject: [PATCH] lsan: Support free_sized and free_aligned_sized from C23
Signed-off-by: Justin King <jcking at google.com>
---
compiler-rt/lib/lsan/lsan_allocator.cpp | 4 +++
compiler-rt/lib/lsan/lsan_allocator.h | 2 ++
compiler-rt/lib/lsan/lsan_interceptors.cpp | 31 +++++++++++++++++++
compiler-rt/lib/lsan/lsan_malloc_mac.cpp | 23 ++++++++------
.../sanitizer_common/sanitizer_malloc_mac.inc | 16 ++++++++++
.../sanitizer_platform_interceptors.h | 13 ++++++++
6 files changed, 79 insertions(+), 10 deletions(-)
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..fe4189b325cc4 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
@@ -103,6 +103,13 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
#endif // SANITIZER_APPLE
+#if SANITIZER_APPLE
+SANITIZER_WEAK_IMPORT void free_sized(void* __ptr, __sanitizer::usize __size);
+SANITIZER_WEAK_IMPORT void free_aligned_sized(void* __ptr,
+ __sanitizer::usize __alignment,
+ __sanitizer::usize __size);
+#endif // SANITIZER_APPLE
+
#if SANITIZER_IOS
#define SI_IOS 1
#else
@@ -663,6 +670,12 @@ 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.
+#define SANITIZER_INTERCEPT_FREE_SIZED defined(__ELF__)
+#define SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED defined(__ELF__)
+
// 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:
More information about the llvm-commits
mailing list