blob: 8dc606802fec350adbd48a1dbae62ed17370d9d6 [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
Mirko Bonadei1127fb92018-06-05 21:44:50 +0200125// Run the callback, and expect a crash if it *doesn't* make an uninitialized
126// memory read. If MSan isn't on, just run the callback.
Alessio Bazzicad31843e2018-04-06 16:18:21 +0200127template <typename F>
128void MsanExpectUninitializedRead(F&& f) {
129#if RTC_HAS_MSAN
Mirko Bonadei1127fb92018-06-05 21:44:50 +0200130 EXPECT_DEATH(f(), "");
131#else
Alessio Bazzicad31843e2018-04-06 16:18:21 +0200132 f();
Alessio Bazzicad31843e2018-04-06 16:18:21 +0200133#endif
134}
135
136} // namespace
137
Mirko Bonadei1127fb92018-06-05 21:44:50 +0200138TEST(SanitizerTest, MsanUninitialized) {
Alessio Bazzicad31843e2018-04-06 16:18:21 +0200139 Bar bar = MsanUninitialized<Bar>({});
140 // Check that a read after initialization is OK.
141 bar.ID = 1;
142 EXPECT_EQ(1u, bar.ID);
143 RTC_LOG(LS_INFO) << "read after init passed";
144 // Check that other fields are uninitialized and equal to zero.
145 MsanExpectUninitializedRead([&] { EXPECT_EQ(0u, bar.foo.field1); });
146 MsanExpectUninitializedRead([&] { EXPECT_EQ(0u, bar.foo.field2); });
147 RTC_LOG(LS_INFO) << "read with no init passed";
148}
149
150} // namespace rtc