Skip to content

Commit 64453c8

Browse files
authored
rtsan: Support free_sized and free_aligned_sized from C23 (#145085)
Adds support to RTSan for `free_sized` and `free_aligned_sized` from C23. Other sanitizers will be handled with their own separate PRs. For #144435 Signed-off-by: Justin King <jcking@google.com>
1 parent 8c32f95 commit 64453c8

File tree

4 files changed

+100
-5
lines changed

4 files changed

+100
-5
lines changed

compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,48 @@ INTERCEPTOR(void, free, void *ptr) {
869869
return REAL(free)(ptr);
870870
}
871871

872+
#if SANITIZER_INTERCEPT_FREE_SIZED
873+
INTERCEPTOR(void, free_sized, void *ptr, SIZE_T size) {
874+
if (DlsymAlloc::PointerIsMine(ptr))
875+
return DlsymAlloc::Free(ptr);
876+
877+
// According to the C and C++ standard, freeing a nullptr is guaranteed to be
878+
// a no-op (and thus real-time safe). This can be confirmed for looking at
879+
// __libc_free in the glibc source.
880+
if (ptr != nullptr)
881+
__rtsan_notify_intercepted_call("free_sized");
882+
883+
if (REAL(free_sized))
884+
return REAL(free_sized)(ptr, size);
885+
return REAL(free)(ptr);
886+
}
887+
#define RTSAN_MAYBE_INTERCEPT_FREE_SIZED INTERCEPT_FUNCTION(free_sized)
888+
#else
889+
#define RTSAN_MAYBE_INTERCEPT_FREE_SIZED
890+
#endif
891+
892+
#if SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED
893+
INTERCEPTOR(void, free_aligned_sized, void *ptr, SIZE_T alignment,
894+
SIZE_T size) {
895+
if (DlsymAlloc::PointerIsMine(ptr))
896+
return DlsymAlloc::Free(ptr);
897+
898+
// According to the C and C++ standard, freeing a nullptr is guaranteed to be
899+
// a no-op (and thus real-time safe). This can be confirmed for looking at
900+
// __libc_free in the glibc source.
901+
if (ptr != nullptr)
902+
__rtsan_notify_intercepted_call("free_aligned_sized");
903+
904+
if (REAL(free_aligned_sized))
905+
return REAL(free_aligned_sized)(ptr, alignment, size);
906+
return REAL(free)(ptr);
907+
}
908+
#define RTSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED \
909+
INTERCEPT_FUNCTION(free_aligned_sized)
910+
#else
911+
#define RTSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED
912+
#endif
913+
872914
INTERCEPTOR(void *, malloc, SIZE_T size) {
873915
if (DlsymAlloc::Use())
874916
return DlsymAlloc::Allocate(size);
@@ -1493,6 +1535,8 @@ INTERCEPTOR(INT_TYPE_SYSCALL, syscall, INT_TYPE_SYSCALL number, ...) {
14931535
void __rtsan::InitializeInterceptors() {
14941536
INTERCEPT_FUNCTION(calloc);
14951537
INTERCEPT_FUNCTION(free);
1538+
RTSAN_MAYBE_INTERCEPT_FREE_SIZED;
1539+
RTSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED;
14961540
INTERCEPT_FUNCTION(malloc);
14971541
INTERCEPT_FUNCTION(realloc);
14981542
INTERCEPT_FUNCTION(reallocf);

compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,14 @@
6363
#define MAYBE_APPEND_64(func) func
6464
#endif
6565

66+
#if SANITIZER_INTERCEPT_FREE_SIZED
67+
extern "C" void free_sized(void *ptr, size_t size);
68+
#endif
69+
70+
#if SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED
71+
extern "C" void free_aligned_sized(void *ptr, size_t alignment, size_t size);
72+
#endif
73+
6674
using namespace testing;
6775
using namespace rtsan_testing;
6876
using namespace std::chrono_literals;
@@ -148,7 +156,6 @@ TEST(TestRtsanInterceptors, AlignedAllocDiesWhenRealtime) {
148156
}
149157
}
150158

151-
// free_sized and free_aligned_sized (both C23) are not yet supported
152159
TEST(TestRtsanInterceptors, FreeDiesWhenRealtime) {
153160
void *ptr_1 = malloc(1);
154161
void *ptr_2 = malloc(1);
@@ -160,11 +167,55 @@ TEST(TestRtsanInterceptors, FreeDiesWhenRealtime) {
160167
ASSERT_NE(nullptr, ptr_2);
161168
}
162169

170+
#if SANITIZER_INTERCEPT_FREE_SIZED
171+
TEST(TestRtsanInterceptors, FreeSizedDiesWhenRealtime) {
172+
void *ptr_1 = malloc(1);
173+
void *ptr_2 = malloc(1);
174+
ExpectRealtimeDeath([ptr_1]() { free_sized(ptr_1, 1); }, "free_sized");
175+
ExpectNonRealtimeSurvival([ptr_2]() { free_sized(ptr_2, 1); });
176+
177+
// Prevent malloc/free pair being optimised out
178+
ASSERT_NE(nullptr, ptr_1);
179+
ASSERT_NE(nullptr, ptr_2);
180+
}
181+
#endif
182+
183+
#if SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED
184+
TEST(TestRtsanInterceptors, FreeAlignedSizedDiesWhenRealtime) {
185+
if (ALIGNED_ALLOC_AVAILABLE()) {
186+
void *ptr_1 = aligned_alloc(16, 32);
187+
void *ptr_2 = aligned_alloc(16, 32);
188+
ExpectRealtimeDeath([ptr_1]() { free_aligned_sized(ptr_1, 16, 32); },
189+
"free_aligned_sized");
190+
ExpectNonRealtimeSurvival([ptr_2]() { free_aligned_sized(ptr_2, 16, 32); });
191+
192+
// Prevent malloc/free pair being optimised out
193+
ASSERT_NE(nullptr, ptr_1);
194+
ASSERT_NE(nullptr, ptr_2);
195+
}
196+
}
197+
#endif
198+
163199
TEST(TestRtsanInterceptors, FreeSurvivesWhenRealtimeIfArgumentIsNull) {
164200
RealtimeInvoke([]() { free(NULL); });
165201
ExpectNonRealtimeSurvival([]() { free(NULL); });
166202
}
167203

204+
#if SANITIZER_INTERCEPT_FREE_SIZED
205+
TEST(TestRtsanInterceptors, FreeSizedSurvivesWhenRealtimeIfArgumentIsNull) {
206+
RealtimeInvoke([]() { free_sized(NULL, 0); });
207+
ExpectNonRealtimeSurvival([]() { free_sized(NULL, 0); });
208+
}
209+
#endif
210+
211+
#if SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED
212+
TEST(TestRtsanInterceptors,
213+
FreeAlignedSizedSurvivesWhenRealtimeIfArgumentIsNull) {
214+
RealtimeInvoke([]() { free_aligned_sized(NULL, 0, 0); });
215+
ExpectNonRealtimeSurvival([]() { free_aligned_sized(NULL, 0, 0); });
216+
}
217+
#endif
218+
168219
TEST(TestRtsanInterceptors, PosixMemalignDiesWhenRealtime) {
169220
auto Func = []() {
170221
void *ptr;

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

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

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

7+
extern void *aligned_alloc(size_t alignment, size_t size);
8+
79
extern void free_aligned_sized(void *p, size_t alignment, size_t size);
810

911
int main() {

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

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

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

7-
extern void *aligned_alloc(size_t alignment, size_t size);
8-
97
extern void free_sized(void *p, size_t size);
108

119
int main() {

0 commit comments

Comments
 (0)