blob: ffbfed7d22f68f98224500ae0736b2ffbb02efff [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
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <stdint.h>
14
Alessio Bazzicad31843e2018-04-06 16:18:21 +020015#include "rtc_base/logging.h"
Yves Gerey3e707812018-11-28 16:47:49 +010016#include "test/gtest.h"
Alessio Bazzicad31843e2018-04-06 16:18:21 +020017
18#if RTC_HAS_MSAN
19#include <sanitizer/msan_interface.h>
20#endif
21
22namespace rtc {
23namespace {
24
25// Test sanitizer_impl::IsTriviallyCopyable (at compile time).
26
27// Trivially copyable.
28
29struct TrTrTr {
30 TrTrTr(const TrTrTr&) = default;
31 TrTrTr& operator=(const TrTrTr&) = default;
32 ~TrTrTr() = default;
33};
34static_assert(sanitizer_impl::IsTriviallyCopyable<TrTrTr>(), "");
35
36struct TrDeTr {
37 TrDeTr(const TrDeTr&) = default;
38 TrDeTr& operator=(const TrDeTr&) = delete;
39 ~TrDeTr() = default;
40};
41static_assert(sanitizer_impl::IsTriviallyCopyable<TrDeTr>(), "");
42
43// Non trivially copyable.
44
45struct TrTrNt {
46 TrTrNt(const TrTrNt&) = default;
47 TrTrNt& operator=(const TrTrNt&) = default;
48 ~TrTrNt();
49};
50static_assert(!sanitizer_impl::IsTriviallyCopyable<TrTrNt>(), "");
51
52struct TrNtTr {
53 TrNtTr(const TrNtTr&) = default;
54 TrNtTr& operator=(const TrNtTr&);
55 ~TrNtTr() = default;
56};
57static_assert(!sanitizer_impl::IsTriviallyCopyable<TrNtTr>(), "");
58
59struct TrNtNt {
60 TrNtNt(const TrNtNt&) = default;
61 TrNtNt& operator=(const TrNtNt&);
62 ~TrNtNt();
63};
64static_assert(!sanitizer_impl::IsTriviallyCopyable<TrNtNt>(), "");
65
66struct TrDeNt {
67 TrDeNt(const TrDeNt&) = default;
68 TrDeNt& operator=(const TrDeNt&) = delete;
69 ~TrDeNt();
70};
71static_assert(!sanitizer_impl::IsTriviallyCopyable<TrDeNt>(), "");
72
73struct NtTrTr {
74 NtTrTr(const NtTrTr&);
75 NtTrTr& operator=(const NtTrTr&) = default;
76 ~NtTrTr() = default;
77};
78static_assert(!sanitizer_impl::IsTriviallyCopyable<NtTrTr>(), "");
79
80struct NtTrNt {
81 NtTrNt(const NtTrNt&);
82 NtTrNt& operator=(const NtTrNt&) = default;
83 ~NtTrNt();
84};
85static_assert(!sanitizer_impl::IsTriviallyCopyable<NtTrNt>(), "");
86
87struct NtNtTr {
88 NtNtTr(const NtNtTr&);
89 NtNtTr& operator=(const NtNtTr&);
90 ~NtNtTr() = default;
91};
92static_assert(!sanitizer_impl::IsTriviallyCopyable<NtNtTr>(), "");
93
94struct NtNtNt {
95 NtNtNt(const NtNtNt&);
96 NtNtNt& operator=(const NtNtNt&);
97 ~NtNtNt();
98};
99static_assert(!sanitizer_impl::IsTriviallyCopyable<NtNtNt>(), "");
100
101struct NtDeTr {
102 NtDeTr(const NtDeTr&);
103 NtDeTr& operator=(const NtDeTr&) = delete;
104 ~NtDeTr() = default;
105};
106static_assert(!sanitizer_impl::IsTriviallyCopyable<NtDeTr>(), "");
107
108struct NtDeNt {
109 NtDeNt(const NtDeNt&);
110 NtDeNt& operator=(const NtDeNt&) = delete;
111 ~NtDeNt();
112};
113static_assert(!sanitizer_impl::IsTriviallyCopyable<NtDeNt>(), "");
114
115// Trivially copyable types.
116
117struct Foo {
118 uint32_t field1;
119 uint16_t field2;
120};
121
122struct Bar {
123 uint32_t ID;
124 Foo foo;
125};
126
Mirko Bonadei1127fb92018-06-05 21:44:50 +0200127// 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.
Alessio Bazzicad31843e2018-04-06 16:18:21 +0200129template <typename F>
130void MsanExpectUninitializedRead(F&& f) {
131#if RTC_HAS_MSAN
Mirko Bonadei1127fb92018-06-05 21:44:50 +0200132 EXPECT_DEATH(f(), "");
133#else
Alessio Bazzicad31843e2018-04-06 16:18:21 +0200134 f();
Alessio Bazzicad31843e2018-04-06 16:18:21 +0200135#endif
136}
137
138} // namespace
139
Mirko Bonadei1127fb92018-06-05 21:44:50 +0200140TEST(SanitizerTest, MsanUninitialized) {
Alessio Bazzicad31843e2018-04-06 16:18:21 +0200141 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