blob: 21ef432fb34289299ca2a6439688a5ef186c680e [file] [log] [blame]
Alessio Bazzicad31843e2018-04-06 16:18:21 +02001/*
2 * Copyright 2018 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
11#include "rtc_base/sanitizer.h"
12
13#include "rtc_base/gunit.h"
14#include "rtc_base/logging.h"
15
16#if RTC_HAS_MSAN
17#include <sanitizer/msan_interface.h>
18#endif
19
20namespace rtc {
21namespace {
22
23// Test sanitizer_impl::IsTriviallyCopyable (at compile time).
24
25// Trivially copyable.
26
27struct TrTrTr {
28 TrTrTr(const TrTrTr&) = default;
29 TrTrTr& operator=(const TrTrTr&) = default;
30 ~TrTrTr() = default;
31};
32static_assert(sanitizer_impl::IsTriviallyCopyable<TrTrTr>(), "");
33
34struct TrDeTr {
35 TrDeTr(const TrDeTr&) = default;
36 TrDeTr& operator=(const TrDeTr&) = delete;
37 ~TrDeTr() = default;
38};
39static_assert(sanitizer_impl::IsTriviallyCopyable<TrDeTr>(), "");
40
41// Non trivially copyable.
42
43struct TrTrNt {
44 TrTrNt(const TrTrNt&) = default;
45 TrTrNt& operator=(const TrTrNt&) = default;
46 ~TrTrNt();
47};
48static_assert(!sanitizer_impl::IsTriviallyCopyable<TrTrNt>(), "");
49
50struct TrNtTr {
51 TrNtTr(const TrNtTr&) = default;
52 TrNtTr& operator=(const TrNtTr&);
53 ~TrNtTr() = default;
54};
55static_assert(!sanitizer_impl::IsTriviallyCopyable<TrNtTr>(), "");
56
57struct TrNtNt {
58 TrNtNt(const TrNtNt&) = default;
59 TrNtNt& operator=(const TrNtNt&);
60 ~TrNtNt();
61};
62static_assert(!sanitizer_impl::IsTriviallyCopyable<TrNtNt>(), "");
63
64struct TrDeNt {
65 TrDeNt(const TrDeNt&) = default;
66 TrDeNt& operator=(const TrDeNt&) = delete;
67 ~TrDeNt();
68};
69static_assert(!sanitizer_impl::IsTriviallyCopyable<TrDeNt>(), "");
70
71struct NtTrTr {
72 NtTrTr(const NtTrTr&);
73 NtTrTr& operator=(const NtTrTr&) = default;
74 ~NtTrTr() = default;
75};
76static_assert(!sanitizer_impl::IsTriviallyCopyable<NtTrTr>(), "");
77
78struct NtTrNt {
79 NtTrNt(const NtTrNt&);
80 NtTrNt& operator=(const NtTrNt&) = default;
81 ~NtTrNt();
82};
83static_assert(!sanitizer_impl::IsTriviallyCopyable<NtTrNt>(), "");
84
85struct NtNtTr {
86 NtNtTr(const NtNtTr&);
87 NtNtTr& operator=(const NtNtTr&);
88 ~NtNtTr() = default;
89};
90static_assert(!sanitizer_impl::IsTriviallyCopyable<NtNtTr>(), "");
91
92struct NtNtNt {
93 NtNtNt(const NtNtNt&);
94 NtNtNt& operator=(const NtNtNt&);
95 ~NtNtNt();
96};
97static_assert(!sanitizer_impl::IsTriviallyCopyable<NtNtNt>(), "");
98
99struct NtDeTr {
100 NtDeTr(const NtDeTr&);
101 NtDeTr& operator=(const NtDeTr&) = delete;
102 ~NtDeTr() = default;
103};
104static_assert(!sanitizer_impl::IsTriviallyCopyable<NtDeTr>(), "");
105
106struct NtDeNt {
107 NtDeNt(const NtDeNt&);
108 NtDeNt& operator=(const NtDeNt&) = delete;
109 ~NtDeNt();
110};
111static_assert(!sanitizer_impl::IsTriviallyCopyable<NtDeNt>(), "");
112
113// Trivially copyable types.
114
115struct Foo {
116 uint32_t field1;
117 uint16_t field2;
118};
119
120struct Bar {
121 uint32_t ID;
122 Foo foo;
123};
124
125// Run the callback, and crash if it *doesn't* make an uninitialized memory
126// read. If MSan isn't on, just run the callback.
127template <typename F>
128void MsanExpectUninitializedRead(F&& f) {
129#if RTC_HAS_MSAN
130 // Allow uninitialized memory reads.
131 RTC_LOG(LS_INFO) << "__msan_set_expect_umr(1)";
132 __msan_set_expect_umr(1);
133#endif
134 f();
135#if RTC_HAS_MSAN
136 // Disallow uninitialized memory reads again, and verify that at least
137 // one uninitialized memory read happened while we weren't looking.
138 RTC_LOG(LS_INFO) << "__msan_set_expect_umr(0)";
139 __msan_set_expect_umr(0);
140#endif
141}
142
143} // namespace
144
145// TODO(b/9116): Enable the test when the bug is fixed.
146TEST(SanitizerTest, DISABLED_MsanUninitialized) {
147 Bar bar = MsanUninitialized<Bar>({});
148 // Check that a read after initialization is OK.
149 bar.ID = 1;
150 EXPECT_EQ(1u, bar.ID);
151 RTC_LOG(LS_INFO) << "read after init passed";
152 // Check that other fields are uninitialized and equal to zero.
153 MsanExpectUninitializedRead([&] { EXPECT_EQ(0u, bar.foo.field1); });
154 MsanExpectUninitializedRead([&] { EXPECT_EQ(0u, bar.foo.field2); });
155 RTC_LOG(LS_INFO) << "read with no init passed";
156}
157
158} // namespace rtc