sanitizer.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /*
  2. * Copyright 2016 The WebRTC Project Authors. All rights reserved.
  3. *
  4. * Use of this source code is governed by a BSD-style license
  5. * that can be found in the LICENSE file in the root of the source
  6. * tree. An additional intellectual property rights grant can be found
  7. * in the file PATENTS. All contributing project authors may
  8. * be found in the AUTHORS file in the root of the source tree.
  9. */
  10. #ifndef RTC_BASE_SANITIZER_H_
  11. #define RTC_BASE_SANITIZER_H_
  12. #include <stddef.h> // For size_t.
  13. #ifdef __cplusplus
  14. #include "absl/meta/type_traits.h"
  15. #endif
  16. #if defined(__has_feature)
  17. #if __has_feature(address_sanitizer)
  18. #define RTC_HAS_ASAN 1
  19. #endif
  20. #if __has_feature(memory_sanitizer)
  21. #define RTC_HAS_MSAN 1
  22. #endif
  23. #endif
  24. #ifndef RTC_HAS_ASAN
  25. #define RTC_HAS_ASAN 0
  26. #endif
  27. #ifndef RTC_HAS_MSAN
  28. #define RTC_HAS_MSAN 0
  29. #endif
  30. #if RTC_HAS_ASAN
  31. #include <sanitizer/asan_interface.h>
  32. #endif
  33. #if RTC_HAS_MSAN
  34. #include <sanitizer/msan_interface.h>
  35. #endif
  36. #ifdef __has_attribute
  37. #if __has_attribute(no_sanitize)
  38. #define RTC_NO_SANITIZE(what) __attribute__((no_sanitize(what)))
  39. #endif
  40. #endif
  41. #ifndef RTC_NO_SANITIZE
  42. #define RTC_NO_SANITIZE(what)
  43. #endif
  44. // Ask ASan to mark the memory range [ptr, ptr + element_size * num_elements)
  45. // as being unaddressable, so that reads and writes are not allowed. ASan may
  46. // narrow the range to the nearest alignment boundaries.
  47. static inline void rtc_AsanPoison(const volatile void* ptr,
  48. size_t element_size,
  49. size_t num_elements) {
  50. #if RTC_HAS_ASAN
  51. ASAN_POISON_MEMORY_REGION(ptr, element_size * num_elements);
  52. #endif
  53. }
  54. // Ask ASan to mark the memory range [ptr, ptr + element_size * num_elements)
  55. // as being addressable, so that reads and writes are allowed. ASan may widen
  56. // the range to the nearest alignment boundaries.
  57. static inline void rtc_AsanUnpoison(const volatile void* ptr,
  58. size_t element_size,
  59. size_t num_elements) {
  60. #if RTC_HAS_ASAN
  61. ASAN_UNPOISON_MEMORY_REGION(ptr, element_size * num_elements);
  62. #endif
  63. }
  64. // Ask MSan to mark the memory range [ptr, ptr + element_size * num_elements)
  65. // as being uninitialized.
  66. static inline void rtc_MsanMarkUninitialized(const volatile void* ptr,
  67. size_t element_size,
  68. size_t num_elements) {
  69. #if RTC_HAS_MSAN
  70. __msan_poison(ptr, element_size * num_elements);
  71. #endif
  72. }
  73. // Force an MSan check (if any bits in the memory range [ptr, ptr +
  74. // element_size * num_elements) are uninitialized the call will crash with an
  75. // MSan report).
  76. static inline void rtc_MsanCheckInitialized(const volatile void* ptr,
  77. size_t element_size,
  78. size_t num_elements) {
  79. #if RTC_HAS_MSAN
  80. __msan_check_mem_is_initialized(ptr, element_size * num_elements);
  81. #endif
  82. }
  83. #ifdef __cplusplus
  84. namespace rtc {
  85. namespace sanitizer_impl {
  86. template <typename T>
  87. constexpr bool IsTriviallyCopyable() {
  88. return static_cast<bool>(absl::is_trivially_copy_constructible<T>::value &&
  89. (absl::is_trivially_copy_assignable<T>::value ||
  90. !std::is_copy_assignable<T>::value) &&
  91. absl::is_trivially_destructible<T>::value);
  92. }
  93. } // namespace sanitizer_impl
  94. template <typename T>
  95. inline void AsanPoison(const T& mem) {
  96. rtc_AsanPoison(mem.data(), sizeof(mem.data()[0]), mem.size());
  97. }
  98. template <typename T>
  99. inline void AsanUnpoison(const T& mem) {
  100. rtc_AsanUnpoison(mem.data(), sizeof(mem.data()[0]), mem.size());
  101. }
  102. template <typename T>
  103. inline void MsanMarkUninitialized(const T& mem) {
  104. rtc_MsanMarkUninitialized(mem.data(), sizeof(mem.data()[0]), mem.size());
  105. }
  106. template <typename T>
  107. inline T MsanUninitialized(T t) {
  108. #if RTC_HAS_MSAN
  109. // TODO(bugs.webrtc.org/8762): Switch to std::is_trivially_copyable when it
  110. // becomes available in downstream projects.
  111. static_assert(sanitizer_impl::IsTriviallyCopyable<T>(), "");
  112. #endif
  113. rtc_MsanMarkUninitialized(&t, sizeof(T), 1);
  114. return t;
  115. }
  116. template <typename T>
  117. inline void MsanCheckInitialized(const T& mem) {
  118. rtc_MsanCheckInitialized(mem.data(), sizeof(mem.data()[0]), mem.size());
  119. }
  120. } // namespace rtc
  121. #endif // __cplusplus
  122. #endif // RTC_BASE_SANITIZER_H_