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