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