blob: 8af0824b67c85bcdedb3efbc35e410e6e01ae99e [file] [log] [blame]
kwibergac554ee2016-09-02 00:39:33 -07001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#ifndef RTC_BASE_SANITIZER_H_
12#define RTC_BASE_SANITIZER_H_
kwibergac554ee2016-09-02 00:39:33 -070013
Alessio Bazzicad31843e2018-04-06 16:18:21 +020014#include <stddef.h> // For size_t.
15
16#ifdef __cplusplus
Jiawei Oua6e034a2018-11-24 20:59:41 -080017#include "absl/meta/type_traits.h"
Alessio Bazzicad31843e2018-04-06 16:18:21 +020018#endif
oprypin8ad0e582017-09-05 03:00:37 -070019
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020020#if defined(__has_feature)
21#if __has_feature(address_sanitizer)
22#define RTC_HAS_ASAN 1
23#endif
24#if __has_feature(memory_sanitizer)
25#define RTC_HAS_MSAN 1
26#endif
27#endif
28#ifndef RTC_HAS_ASAN
29#define RTC_HAS_ASAN 0
30#endif
31#ifndef RTC_HAS_MSAN
32#define RTC_HAS_MSAN 0
33#endif
kwibergac554ee2016-09-02 00:39:33 -070034
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020035#if RTC_HAS_ASAN
36#include <sanitizer/asan_interface.h>
37#endif
38#if RTC_HAS_MSAN
39#include <sanitizer/msan_interface.h>
40#endif
41
42#ifdef __has_attribute
43#if __has_attribute(no_sanitize)
44#define RTC_NO_SANITIZE(what) __attribute__((no_sanitize(what)))
45#endif
46#endif
47#ifndef RTC_NO_SANITIZE
48#define RTC_NO_SANITIZE(what)
49#endif
50
51// Ask ASan to mark the memory range [ptr, ptr + element_size * num_elements)
52// as being unaddressable, so that reads and writes are not allowed. ASan may
53// narrow the range to the nearest alignment boundaries.
54static inline void rtc_AsanPoison(const volatile void* ptr,
55 size_t element_size,
56 size_t num_elements) {
57#if RTC_HAS_ASAN
58 ASAN_POISON_MEMORY_REGION(ptr, element_size * num_elements);
59#endif
60}
61
62// Ask ASan to mark the memory range [ptr, ptr + element_size * num_elements)
63// as being addressable, so that reads and writes are allowed. ASan may widen
64// the range to the nearest alignment boundaries.
65static inline void rtc_AsanUnpoison(const volatile void* ptr,
66 size_t element_size,
67 size_t num_elements) {
68#if RTC_HAS_ASAN
69 ASAN_UNPOISON_MEMORY_REGION(ptr, element_size * num_elements);
70#endif
71}
72
73// Ask MSan to mark the memory range [ptr, ptr + element_size * num_elements)
74// as being uninitialized.
75static inline void rtc_MsanMarkUninitialized(const volatile void* ptr,
76 size_t element_size,
77 size_t num_elements) {
78#if RTC_HAS_MSAN
79 __msan_poison(ptr, element_size * num_elements);
80#endif
81}
82
83// Force an MSan check (if any bits in the memory range [ptr, ptr +
84// element_size * num_elements) are uninitialized the call will crash with an
85// MSan report).
86static inline void rtc_MsanCheckInitialized(const volatile void* ptr,
87 size_t element_size,
88 size_t num_elements) {
89#if RTC_HAS_MSAN
90 __msan_check_mem_is_initialized(ptr, element_size * num_elements);
91#endif
92}
93
94#ifdef __cplusplus
95
96namespace rtc {
Alessio Bazzicad31843e2018-04-06 16:18:21 +020097namespace sanitizer_impl {
98
99template <typename T>
100constexpr bool IsTriviallyCopyable() {
Jiawei Oua6e034a2018-11-24 20:59:41 -0800101 return static_cast<bool>(absl::is_trivially_copy_constructible<T>::value &&
102 (absl::is_trivially_copy_assignable<T>::value ||
Alessio Bazzicad31843e2018-04-06 16:18:21 +0200103 !std::is_copy_assignable<T>::value) &&
Jiawei Oua6e034a2018-11-24 20:59:41 -0800104 absl::is_trivially_destructible<T>::value);
Alessio Bazzicad31843e2018-04-06 16:18:21 +0200105}
106
107} // namespace sanitizer_impl
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200108
109template <typename T>
110inline void AsanPoison(const T& mem) {
111 rtc_AsanPoison(mem.data(), sizeof(mem.data()[0]), mem.size());
112}
113
114template <typename T>
115inline void AsanUnpoison(const T& mem) {
116 rtc_AsanUnpoison(mem.data(), sizeof(mem.data()[0]), mem.size());
117}
118
119template <typename T>
120inline void MsanMarkUninitialized(const T& mem) {
121 rtc_MsanMarkUninitialized(mem.data(), sizeof(mem.data()[0]), mem.size());
122}
123
124template <typename T>
Alessio Bazzicad31843e2018-04-06 16:18:21 +0200125inline T MsanUninitialized(T t) {
Alessio Bazzicae6c2c082018-11-08 12:20:55 +0100126#if RTC_HAS_MSAN
Alessio Bazzicad31843e2018-04-06 16:18:21 +0200127 // TODO(bugs.webrtc.org/8762): Switch to std::is_trivially_copyable when it
128 // becomes available in downstream projects.
129 static_assert(sanitizer_impl::IsTriviallyCopyable<T>(), "");
Alessio Bazzicae6c2c082018-11-08 12:20:55 +0100130#endif
Alessio Bazzicad31843e2018-04-06 16:18:21 +0200131 rtc_MsanMarkUninitialized(&t, sizeof(T), 1);
132 return t;
133}
134
135template <typename T>
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200136inline void MsanCheckInitialized(const T& mem) {
137 rtc_MsanCheckInitialized(mem.data(), sizeof(mem.data()[0]), mem.size());
138}
139
140} // namespace rtc
141
142#endif // __cplusplus
kwibergac554ee2016-09-02 00:39:33 -0700143
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200144#endif // RTC_BASE_SANITIZER_H_