Skip to content

Commit 2fb2f1d

Browse files
committed
lsan: Support free_sized and free_aligned_sized from C23
Signed-off-by: Justin King <[email protected]>
1 parent d9f7979 commit 2fb2f1d

File tree

8 files changed

+79
-12
lines changed

8 files changed

+79
-12
lines changed

compiler-rt/lib/lsan/lsan_allocator.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,10 @@ void lsan_free(void *p) {
220220
Deallocate(p);
221221
}
222222

223+
void lsan_free_sized(void *p, uptr) { Deallocate(p); }
224+
225+
void lsan_free_aligned_sized(void *p, uptr, uptr) { Deallocate(p); }
226+
223227
void *lsan_realloc(void *p, uptr size, const StackTrace &stack) {
224228
return SetErrnoOnNull(Reallocate(stack, p, size, 1));
225229
}

compiler-rt/lib/lsan/lsan_allocator.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ void *lsan_aligned_alloc(uptr alignment, uptr size, const StackTrace &stack);
127127
void *lsan_memalign(uptr alignment, uptr size, const StackTrace &stack);
128128
void *lsan_malloc(uptr size, const StackTrace &stack);
129129
void lsan_free(void *p);
130+
void lsan_free_sized(void *p, uptr size);
131+
void lsan_free_aligned_sized(void *p, uptr alignment, uptr size);
130132
void *lsan_realloc(void *p, uptr size, const StackTrace &stack);
131133
void *lsan_reallocarray(void *p, uptr nmemb, uptr size,
132134
const StackTrace &stack);

compiler-rt/lib/lsan/lsan_interceptors.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,35 @@ INTERCEPTOR(void, free, void *p) {
8484
lsan_free(p);
8585
}
8686

87+
# if SANITIZER_INTERCEPT_FREE_SIZED
88+
INTERCEPTOR(void, free_sized, void *p, uptr size) {
89+
if (UNLIKELY(!p))
90+
return;
91+
if (DlsymAlloc::PointerIsMine(p))
92+
return DlsymAlloc::Free(p);
93+
ENSURE_LSAN_INITED;
94+
lsan_free_sized(p, size);
95+
}
96+
# define LSAN_MAYBE_INTERCEPT_FREE_SIZED INTERCEPT_FUNCTION(free_sized)
97+
# else
98+
# define LSAN_MAYBE_INTERCEPT_FREE_SIZED
99+
# endif
100+
101+
# if SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED
102+
INTERCEPTOR(void, free_aligned_sized, void *p, uptr alignment, uptr size) {
103+
if (UNLIKELY(!p))
104+
return;
105+
if (DlsymAlloc::PointerIsMine(p))
106+
return DlsymAlloc::Free(p);
107+
ENSURE_LSAN_INITED;
108+
lsan_free_aligned_sized(p, alignment, size);
109+
}
110+
# define LSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED \
111+
INTERCEPT_FUNCTION(free_aligned_sized)
112+
# else
113+
# define LSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED
114+
# endif
115+
87116
INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
88117
if (DlsymAlloc::Use())
89118
return DlsymAlloc::Callocate(nmemb, size);
@@ -547,6 +576,8 @@ void InitializeInterceptors() {
547576

548577
INTERCEPT_FUNCTION(malloc);
549578
INTERCEPT_FUNCTION(free);
579+
LSAN_MAYBE_INTERCEPT_FREE_SIZED;
580+
LSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED;
550581
LSAN_MAYBE_INTERCEPT_CFREE;
551582
INTERCEPT_FUNCTION(calloc);
552583
INTERCEPT_FUNCTION(realloc);

compiler-rt/lib/lsan/lsan_malloc_mac.cpp

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,19 @@ using namespace __lsan;
4444
void *p = lsan_valloc(size, stack)
4545
#define COMMON_MALLOC_FREE(ptr) \
4646
lsan_free(ptr)
47-
#define COMMON_MALLOC_SIZE(ptr) \
48-
uptr size = lsan_mz_size(ptr)
49-
#define COMMON_MALLOC_FILL_STATS(zone, stats)
50-
#define COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name) \
51-
(void)zone_name; \
52-
Report("mz_realloc(%p) -- attempting to realloc unallocated memory.\n", ptr);
53-
#define COMMON_MALLOC_NAMESPACE __lsan
54-
#define COMMON_MALLOC_HAS_ZONE_ENUMERATOR 0
55-
#define COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT 0
47+
# define COMMON_MALLOC_FREE_SIZED(ptr, size) lsan_free_sized(ptr, size)
48+
# define COMMON_MALLOC_FREE_ALIGNED_SIZED(ptr, alignment, size) \
49+
lsan_free_aligned_sized(ptr, alignment, size)
50+
# define COMMON_MALLOC_SIZE(ptr) uptr size = lsan_mz_size(ptr)
51+
# define COMMON_MALLOC_FILL_STATS(zone, stats)
52+
# define COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name) \
53+
(void)zone_name; \
54+
Report("mz_realloc(%p) -- attempting to realloc unallocated memory.\n", \
55+
ptr);
56+
# define COMMON_MALLOC_NAMESPACE __lsan
57+
# define COMMON_MALLOC_HAS_ZONE_ENUMERATOR 0
58+
# define COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT 0
5659

57-
#include "sanitizer_common/sanitizer_malloc_mac.inc"
60+
# include "sanitizer_common/sanitizer_malloc_mac.inc"
5861

5962
#endif // SANITIZER_APPLE

compiler-rt/lib/sanitizer_common/sanitizer_malloc_mac.inc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,22 @@ INTERCEPTOR(void, free, void *ptr) {
144144
COMMON_MALLOC_FREE(ptr);
145145
}
146146

147+
#if SANITIZER_INTERCEPT_FREE_SIZED && defined(COMMON_MALLOC_FREE_SIZED)
148+
INTERCEPTOR(void, free_sized, void *ptr, size_t size) {
149+
COMMON_MALLOC_ENTER();
150+
COMMON_MALLOC_FREE_SIZED(ptr, size);
151+
}
152+
#endif
153+
154+
#if SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED && \
155+
defined(COMMON_MALLOC_FREE_ALIGNED_SIZED)
156+
INTERCEPTOR(void, free_aligned_sized, void *ptr, size_t alignment,
157+
size_t size) {
158+
COMMON_MALLOC_ENTER();
159+
COMMON_MALLOC_FREE_ALIGNED_SIZED(ptr, alignment, size);
160+
}
161+
#endif
162+
147163
INTERCEPTOR(void *, realloc, void *ptr, size_t size) {
148164
COMMON_MALLOC_ENTER();
149165
COMMON_MALLOC_REALLOC(ptr, size);

compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,17 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
663663
#define SANITIZER_INTERCEPT_GETSERVBYNAME_R SI_GLIBC
664664
#define SANITIZER_INTERCEPT_GETSERVBYPORT_R SI_GLIBC
665665

666+
// Until free_sized and free_aligned_sized are more generally available,
667+
// we can only unconditionally intercept on ELF-based platforms where it
668+
// is okay to have undefined weak symbols.
669+
#ifdef __ELF__
670+
# define SANITIZER_INTERCEPT_FREE_SIZED 1
671+
# define SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED 1
672+
#else
673+
# define SANITIZER_INTERCEPT_FREE_SIZED 0
674+
# define SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED 0
675+
#endif
676+
666677
// This macro gives a way for downstream users to override the above
667678
// interceptor macros irrespective of the platform they are on. They have
668679
// to do two things:

compiler-rt/test/sanitizer_common/TestCases/Linux/free_aligned_sized.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// RUN: %clang -std=c23 -O0 %s -o %t && %run %t
2-
// UNSUPPORTED: asan, hwasan, rtsan, tsan, msan, lsan, ubsan
2+
// UNSUPPORTED: asan, hwasan, rtsan, tsan, msan, ubsan
33

44
#include <stddef.h>
55
#include <stdlib.h>

compiler-rt/test/sanitizer_common/TestCases/Linux/free_sized.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// RUN: %clang -std=c23 -O0 %s -o %t && %run %t
2-
// UNSUPPORTED: asan, hwasan, rtsan, tsan, msan, lsan, ubsan
2+
// UNSUPPORTED: asan, hwasan, rtsan, tsan, msan, ubsan
33

44
#include <stddef.h>
55
#include <stdlib.h>

0 commit comments

Comments
 (0)