diff --git a/compiler-rt/include/CMakeLists.txt b/compiler-rt/include/CMakeLists.txt index d598a94ee2e23..242d62b9b447b 100644 --- a/compiler-rt/include/CMakeLists.txt +++ b/compiler-rt/include/CMakeLists.txt @@ -10,6 +10,7 @@ if (COMPILER_RT_BUILD_SANITIZERS) sanitizer/lsan_interface.h sanitizer/msan_interface.h sanitizer/netbsd_syscall_hooks.h + sanitizer/rtsan_interface.h sanitizer/scudo_interface.h sanitizer/tsan_interface.h sanitizer/tsan_interface_atomic.h diff --git a/compiler-rt/include/sanitizer/rtsan_interface.h b/compiler-rt/include/sanitizer/rtsan_interface.h new file mode 100644 index 0000000000000..5d7ce5345712e --- /dev/null +++ b/compiler-rt/include/sanitizer/rtsan_interface.h @@ -0,0 +1,75 @@ +//===-- sanitizer/rtsan_interface.h -----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is a part of RealtimeSanitizer. +// +// Public interface header. +//===----------------------------------------------------------------------===// + +#ifndef SANITIZER_RTSAN_INTERFACE_H +#define SANITIZER_RTSAN_INTERFACE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// Disable all RTSan error reporting. +// Must be paired with a call to `__rtsan_enable` +void SANITIZER_CDECL __rtsan_disable(void); + +// Re-enable all RTSan error reporting. +// Must follow a call to `__rtsan_disable`. +void SANITIZER_CDECL __rtsan_enable(void); + +#ifdef __cplusplus +} // extern "C" + +namespace __rtsan { +#if defined(__has_feature) && __has_feature(realtime_sanitizer) + +class ScopedDisabler { +public: + ScopedDisabler() { __rtsan_disable(); } + ~ScopedDisabler() { __rtsan_enable(); } + +#if __cplusplus >= 201103L + ScopedDisabler(const ScopedDisabler &) = delete; + ScopedDisabler &operator=(const ScopedDisabler &) = delete; + ScopedDisabler(ScopedDisabler &&) = delete; + ScopedDisabler &operator=(ScopedDisabler &&) = delete; +#else +private: + ScopedDisabler(const ScopedDisabler &); + ScopedDisabler &operator=(const ScopedDisabler &); +#endif // __cplusplus >= 201103L +}; + +#else + +class ScopedDisabler { +public: + ScopedDisabler() {} +#if __cplusplus >= 201103L + ScopedDisabler(const ScopedDisabler &) = delete; + ScopedDisabler &operator=(const ScopedDisabler &) = delete; + ScopedDisabler(ScopedDisabler &&) = delete; + ScopedDisabler &operator=(ScopedDisabler &&) = delete; +#else +private: + ScopedDisabler(const ScopedDisabler &); + ScopedDisabler &operator=(const ScopedDisabler &); +#endif // __cplusplus >= 201103L +}; + +#endif // defined(__has_feature) && __has_feature(realtime_sanitizer) +} // namespace __rtsan +#endif // __cplusplus + +#endif // SANITIZER_RTSAN_INTERFACE_H diff --git a/compiler-rt/lib/rtsan/rtsan.h b/compiler-rt/lib/rtsan/rtsan.h index ae23609f97d2d..ca72d41d11125 100644 --- a/compiler-rt/lib/rtsan/rtsan.h +++ b/compiler-rt/lib/rtsan/rtsan.h @@ -36,12 +36,10 @@ SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_realtime_enter(); // intercepted method calls to the real methods. SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_realtime_exit(); -// Disable all RTSan error reporting. -// Injected into the code if "nosanitize(realtime)" is on a function. +// See documentation in rtsan_interface.h. SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_disable(); -// Re-enable all RTSan error reporting. -// The counterpart to `__rtsan_disable`. +// See documentation in rtsan_interface.h. SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_enable(); SANITIZER_INTERFACE_ATTRIBUTE void diff --git a/compiler-rt/test/rtsan/disabler.cpp b/compiler-rt/test/rtsan/disabler.cpp new file mode 100644 index 0000000000000..0a6411a2be694 --- /dev/null +++ b/compiler-rt/test/rtsan/disabler.cpp @@ -0,0 +1,53 @@ +// RUN: %clangxx -fsanitize=realtime %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s +// RUN: %clangxx %s -fsanitize=realtime -o - -S -emit-llvm | FileCheck %s --check-prefix=CHECK-ENABLED-IR +// RUN: %clangxx %s -o - -S -emit-llvm | FileCheck %s --check-prefix=CHECK-DISABLED-IR +// UNSUPPORTED: ios + +#include +#include + +#include "sanitizer/rtsan_interface.h" + +void violation() [[clang::nonblocking]] { + void *ptr; + { + __rtsan::ScopedDisabler disabler{}; + ptr = malloc(2); + fprintf(stderr, "Allocated pointer %p in disabled context\n", ptr); + } + + // ensure nested disablers don't interfere with one another + { + void *ptr2; + __rtsan::ScopedDisabler disabler{}; + { + __rtsan::ScopedDisabler disabler2{}; + ptr2 = malloc(2); + fprintf(stderr, "Allocated second pointer %p in disabled context\n", + ptr2); + } + + free(ptr2); + fprintf(stderr, "Free'd second pointer in disabled context\n"); + } + + free(ptr); +} + +int main() { + violation(); + return 0; + // CHECK: Allocated pointer {{.*}} in disabled context + // CHECK: Allocated second pointer {{.*}} in disabled context + // CHECK: Free'd second pointer in disabled context + // CHECK: {{.*Real-time violation.*}} + // CHECK-NOT: {{.*malloc*}} + // CHECK-NEXT: {{.*free.*}} +} + +// CHECK-ENABLED-IR: {{.*@__rtsan_disable.*}} +// CHECK-ENABLED-IR: {{.*@__rtsan_enable.*}} + +// CHECK-DISABLED-IR-NOT: {{.*__rtsan_disable.*}} +// CHECK-DISABLED-IR-NOT: {{.*__rtsan_enable.*}}