Skip to content

rtsan: Support free_sized and free_aligned_sized from C23 #145085

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

jcking
Copy link
Contributor

@jcking jcking commented Jun 20, 2025

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>
@llvmbot
Copy link
Member

llvmbot commented Jun 20, 2025

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

Author: Justin King (jcking)

Changes

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


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 --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;
 }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy