[compiler-rt] rtsan: Support free_sized and free_aligned_sized from C23 (PR #145085)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 20 10:56:10 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: Justin King (jcking)

<details>
<summary>Changes</summary>

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

---
Full diff: https://github.com/llvm/llvm-project/pull/145085.diff


3 Files Affected:

- (modified) compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp (+44) 
- (modified) compiler-rt/test/sanitizer_common/TestCases/Linux/free_aligned_sized.c (+13-1) 
- (modified) compiler-rt/test/sanitizer_common/TestCases/Linux/free_sized.c (+10-2) 


``````````diff
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/test/sanitizer_common/TestCases/Linux/free_aligned_sized.c b/compiler-rt/test/sanitizer_common/TestCases/Linux/free_aligned_sized.c
index 7710c62368191..42a68b76db902 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,13 +1,25 @@
 // RUN: %clang -std=c23 -O0 %s -o %t && %run %t
-// UNSUPPORTED: asan, hwasan, rtsan, tsan, ubsan
+// UNSUPPORTED: asan, hwasan, tsan, ubsan
 
 #include <stddef.h>
 #include <stdlib.h>
 
+#if defined(__has_feature) && __has_feature(realtime_sanitizer)
+#  include <sanitizer/rtsan_interface.h>
+#endif
+
+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() {
+#if defined(__has_feature) && __has_feature(realtime_sanitizer)
+  __rtsan_disable();
+#endif
   volatile void *p = aligned_alloc(128, 1024);
   free_aligned_sized((void *)p, 128, 1024);
+#if defined(__has_feature) && __has_feature(realtime_sanitizer)
+  __rtsan_enable();
+#endif
   return 0;
 }
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 9eac562fecb03..8453bcf07974a 100644
--- a/compiler-rt/test/sanitizer_common/TestCases/Linux/free_sized.c
+++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/free_sized.c
@@ -1,15 +1,23 @@
 // RUN: %clang -std=c23 -O0 %s -o %t && %run %t
-// UNSUPPORTED: asan, hwasan, rtsan, tsan, ubsan
+// UNSUPPORTED: asan, hwasan, tsan, ubsan
 
 #include <stddef.h>
 #include <stdlib.h>
 
-extern void *aligned_alloc(size_t alignment, size_t size);
+#if defined(__has_feature) && __has_feature(realtime_sanitizer)
+#  include <sanitizer/rtsan_interface.h>
+#endif
 
 extern void free_sized(void *p, size_t size);
 
 int main() {
+#if defined(__has_feature) && __has_feature(realtime_sanitizer)
+  __rtsan_disable();
+#endif
   volatile void *p = malloc(64);
   free_sized((void *)p, 64);
+#if defined(__has_feature) && __has_feature(realtime_sanitizer)
+  __rtsan_enable();
+#endif
   return 0;
 }

``````````

</details>


https://github.com/llvm/llvm-project/pull/145085


More information about the llvm-commits mailing list