[compiler-rt] 64453c8 - rtsan: Support free_sized and free_aligned_sized from C23 (#145085)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 9 10:37:03 PDT 2025
Author: Justin King
Date: 2025-07-09T10:36:59-07:00
New Revision: 64453c802eca9bd839e2fb43d1a6a1b0e7c83e58
URL: https://github.com/llvm/llvm-project/commit/64453c802eca9bd839e2fb43d1a6a1b0e7c83e58
DIFF: https://github.com/llvm/llvm-project/commit/64453c802eca9bd839e2fb43d1a6a1b0e7c83e58.diff
LOG: 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 https://github.com/llvm/llvm-project/issues/144435
Signed-off-by: Justin King <jcking at google.com>
Added:
Modified:
compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
compiler-rt/test/sanitizer_common/TestCases/Linux/free_aligned_sized.c
compiler-rt/test/sanitizer_common/TestCases/Linux/free_sized.c
Removed:
################################################################################
diff --git a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
index 9f9ffd4313810..a9d864e9fe926 100644
--- a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
+++ b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
@@ -869,6 +869,48 @@ INTERCEPTOR(void, free, void *ptr) {
return REAL(free)(ptr);
}
+#if SANITIZER_INTERCEPT_FREE_SIZED
+INTERCEPTOR(void, free_sized, void *ptr, SIZE_T size) {
+ if (DlsymAlloc::PointerIsMine(ptr))
+ return DlsymAlloc::Free(ptr);
+
+ // According to the C and C++ standard, freeing a nullptr is guaranteed to be
+ // a no-op (and thus real-time safe). This can be confirmed for looking at
+ // __libc_free in the glibc source.
+ if (ptr != nullptr)
+ __rtsan_notify_intercepted_call("free_sized");
+
+ if (REAL(free_sized))
+ return REAL(free_sized)(ptr, size);
+ return REAL(free)(ptr);
+}
+#define RTSAN_MAYBE_INTERCEPT_FREE_SIZED INTERCEPT_FUNCTION(free_sized)
+#else
+#define RTSAN_MAYBE_INTERCEPT_FREE_SIZED
+#endif
+
+#if SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED
+INTERCEPTOR(void, free_aligned_sized, void *ptr, SIZE_T alignment,
+ SIZE_T size) {
+ if (DlsymAlloc::PointerIsMine(ptr))
+ return DlsymAlloc::Free(ptr);
+
+ // According to the C and C++ standard, freeing a nullptr is guaranteed to be
+ // a no-op (and thus real-time safe). This can be confirmed for looking at
+ // __libc_free in the glibc source.
+ if (ptr != nullptr)
+ __rtsan_notify_intercepted_call("free_aligned_sized");
+
+ if (REAL(free_aligned_sized))
+ return REAL(free_aligned_sized)(ptr, alignment, size);
+ return REAL(free)(ptr);
+}
+#define RTSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED \
+ INTERCEPT_FUNCTION(free_aligned_sized)
+#else
+#define RTSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED
+#endif
+
INTERCEPTOR(void *, malloc, SIZE_T size) {
if (DlsymAlloc::Use())
return DlsymAlloc::Allocate(size);
@@ -1493,6 +1535,8 @@ INTERCEPTOR(INT_TYPE_SYSCALL, syscall, INT_TYPE_SYSCALL number, ...) {
void __rtsan::InitializeInterceptors() {
INTERCEPT_FUNCTION(calloc);
INTERCEPT_FUNCTION(free);
+ RTSAN_MAYBE_INTERCEPT_FREE_SIZED;
+ RTSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED;
INTERCEPT_FUNCTION(malloc);
INTERCEPT_FUNCTION(realloc);
INTERCEPT_FUNCTION(reallocf);
diff --git a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
index 2ee35555c24de..26a3b252d3b6b 100644
--- a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
+++ b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
@@ -63,6 +63,14 @@
#define MAYBE_APPEND_64(func) func
#endif
+#if SANITIZER_INTERCEPT_FREE_SIZED
+extern "C" void free_sized(void *ptr, size_t size);
+#endif
+
+#if SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED
+extern "C" void free_aligned_sized(void *ptr, size_t alignment, size_t size);
+#endif
+
using namespace testing;
using namespace rtsan_testing;
using namespace std::chrono_literals;
@@ -148,7 +156,6 @@ TEST(TestRtsanInterceptors, AlignedAllocDiesWhenRealtime) {
}
}
-// free_sized and free_aligned_sized (both C23) are not yet supported
TEST(TestRtsanInterceptors, FreeDiesWhenRealtime) {
void *ptr_1 = malloc(1);
void *ptr_2 = malloc(1);
@@ -160,11 +167,55 @@ TEST(TestRtsanInterceptors, FreeDiesWhenRealtime) {
ASSERT_NE(nullptr, ptr_2);
}
+#if SANITIZER_INTERCEPT_FREE_SIZED
+TEST(TestRtsanInterceptors, FreeSizedDiesWhenRealtime) {
+ void *ptr_1 = malloc(1);
+ void *ptr_2 = malloc(1);
+ ExpectRealtimeDeath([ptr_1]() { free_sized(ptr_1, 1); }, "free_sized");
+ ExpectNonRealtimeSurvival([ptr_2]() { free_sized(ptr_2, 1); });
+
+ // Prevent malloc/free pair being optimised out
+ ASSERT_NE(nullptr, ptr_1);
+ ASSERT_NE(nullptr, ptr_2);
+}
+#endif
+
+#if SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED
+TEST(TestRtsanInterceptors, FreeAlignedSizedDiesWhenRealtime) {
+ if (ALIGNED_ALLOC_AVAILABLE()) {
+ void *ptr_1 = aligned_alloc(16, 32);
+ void *ptr_2 = aligned_alloc(16, 32);
+ ExpectRealtimeDeath([ptr_1]() { free_aligned_sized(ptr_1, 16, 32); },
+ "free_aligned_sized");
+ ExpectNonRealtimeSurvival([ptr_2]() { free_aligned_sized(ptr_2, 16, 32); });
+
+ // Prevent malloc/free pair being optimised out
+ ASSERT_NE(nullptr, ptr_1);
+ ASSERT_NE(nullptr, ptr_2);
+ }
+}
+#endif
+
TEST(TestRtsanInterceptors, FreeSurvivesWhenRealtimeIfArgumentIsNull) {
RealtimeInvoke([]() { free(NULL); });
ExpectNonRealtimeSurvival([]() { free(NULL); });
}
+#if SANITIZER_INTERCEPT_FREE_SIZED
+TEST(TestRtsanInterceptors, FreeSizedSurvivesWhenRealtimeIfArgumentIsNull) {
+ RealtimeInvoke([]() { free_sized(NULL, 0); });
+ ExpectNonRealtimeSurvival([]() { free_sized(NULL, 0); });
+}
+#endif
+
+#if SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED
+TEST(TestRtsanInterceptors,
+ FreeAlignedSizedSurvivesWhenRealtimeIfArgumentIsNull) {
+ RealtimeInvoke([]() { free_aligned_sized(NULL, 0, 0); });
+ ExpectNonRealtimeSurvival([]() { free_aligned_sized(NULL, 0, 0); });
+}
+#endif
+
TEST(TestRtsanInterceptors, PosixMemalignDiesWhenRealtime) {
auto Func = []() {
void *ptr;
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 dc11e7fa5e9b3..15b1a43f596e8 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,9 +1,11 @@
// RUN: %clang -std=c23 -O0 %s -o %t && %run %t
-// UNSUPPORTED: asan, hwasan, rtsan, ubsan
+// UNSUPPORTED: asan, hwasan, ubsan
#include <stddef.h>
#include <stdlib.h>
+extern void *aligned_alloc(size_t alignment, size_t size);
+
extern void free_aligned_sized(void *p, size_t alignment, size_t size);
int main() {
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 7a993d481bc5a..d8ec1e8b364b6 100644
--- a/compiler-rt/test/sanitizer_common/TestCases/Linux/free_sized.c
+++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/free_sized.c
@@ -1,11 +1,9 @@
// RUN: %clang -std=c23 -O0 %s -o %t && %run %t
-// UNSUPPORTED: asan, hwasan, rtsan, ubsan
+// UNSUPPORTED: asan, hwasan, ubsan
#include <stddef.h>
#include <stdlib.h>
-extern void *aligned_alloc(size_t alignment, size_t size);
-
extern void free_sized(void *p, size_t size);
int main() {
More information about the llvm-commits
mailing list