1 /*
2 * Copyright (c) 2017 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 <stddef.h>
12 #include <stdio.h>
13
14 #include <memory>
15 #include <random>
16
17 #include "rtc_base/checks.h"
18 #include "rtc_base/null_socket_server.h"
19 #include "rtc_base/thread.h"
20 #include "test/gtest.h"
21
22 namespace rtc {
23
24 namespace {
25
26 #if defined(MEMORY_SANITIZER)
UseOfUninitializedValue()27 void UseOfUninitializedValue() {
28 int* buf = new int[2];
29 std::random_device engine;
30 if (buf[engine() % 2]) { // Non-deterministic conditional.
31 printf("Externally visible action.");
32 }
33 delete[] buf;
34 }
35
TEST(SanitizersDeathTest,MemorySanitizer)36 TEST(SanitizersDeathTest, MemorySanitizer) {
37 EXPECT_DEATH(UseOfUninitializedValue(), "use-of-uninitialized-value");
38 }
39 #endif
40
41 #if defined(ADDRESS_SANITIZER)
HeapUseAfterFree()42 void HeapUseAfterFree() {
43 char* buf = new char[2];
44 delete[] buf;
45 buf[0] = buf[1];
46 }
47
TEST(SanitizersDeathTest,AddressSanitizer)48 TEST(SanitizersDeathTest, AddressSanitizer) {
49 EXPECT_DEATH(HeapUseAfterFree(), "heap-use-after-free");
50 }
51 #endif
52
53 #if defined(UNDEFINED_SANITIZER)
54 // For ubsan:
SignedIntegerOverflow()55 void SignedIntegerOverflow() {
56 int32_t x = 1234567890;
57 x *= 2;
58 }
59
60 // For ubsan_vptr:
61 struct Base {
frtc::__anonf1ecffee0111::Base62 virtual void f() {}
~Basertc::__anonf1ecffee0111::Base63 virtual ~Base() {}
64 };
65 struct Derived : public Base {};
66
InvalidVptr()67 void InvalidVptr() {
68 Base b;
69 auto* d = static_cast<Derived*>(&b); // Bad downcast.
70 d->f(); // Virtual function call with object of wrong dynamic type.
71 }
72
TEST(SanitizersDeathTest,UndefinedSanitizer)73 TEST(SanitizersDeathTest, UndefinedSanitizer) {
74 EXPECT_DEATH(
75 {
76 SignedIntegerOverflow();
77 InvalidVptr();
78 },
79 "runtime error");
80 }
81 #endif
82
83 #if defined(THREAD_SANITIZER)
84 class IncrementThread : public Thread {
85 public:
IncrementThread(int * value)86 explicit IncrementThread(int* value)
87 : Thread(std::make_unique<NullSocketServer>()), value_(value) {}
88
Run()89 void Run() override {
90 ++*value_;
91 Thread::Current()->SleepMs(100);
92 }
93
94 // Un-protect Thread::Join for the test.
Join()95 void Join() { Thread::Join(); }
96
97 private:
98 int* value_;
99
100 RTC_DISALLOW_COPY_AND_ASSIGN(IncrementThread);
101 };
102
DataRace()103 void DataRace() {
104 int value = 0;
105 IncrementThread thread1(&value);
106 IncrementThread thread2(&value);
107 thread1.Start();
108 thread2.Start();
109 thread1.Join();
110 thread2.Join();
111 // TSan seems to mess with gtest's death detection.
112 // Fail intentionally, and rely on detecting the error message.
113 RTC_CHECK(false);
114 }
115
TEST(SanitizersDeathTest,ThreadSanitizer)116 TEST(SanitizersDeathTest, ThreadSanitizer) {
117 EXPECT_DEATH(DataRace(), "data race");
118 }
119 #endif
120
121 } // namespace
122
123 } // namespace rtc
124