blob: 077cf7e699544c58726674c8a89e9b1142858c0d [file] [log] [blame]
Oleh Prypin66ca7e32017-09-14 13:05:00 +02001/*
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#include <random>
14
Karl Wiberg918f50c2018-07-05 11:40:33 +020015#include "absl/memory/memory.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "rtc_base/checks.h"
17#include "rtc_base/nullsocketserver.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "rtc_base/thread.h"
19#include "test/gtest.h"
Oleh Prypin66ca7e32017-09-14 13:05:00 +020020
21namespace rtc {
22
23namespace {
24
25#if defined(MEMORY_SANITIZER)
26void UseOfUninitializedValue() {
27 int* buf = new int[2];
28 std::random_device engine;
29 if (buf[engine() % 2]) { // Non-deterministic conditional.
30 printf("Externally visible action.");
31 }
32 delete[] buf;
33}
34
35TEST(SanitizersDeathTest, MemorySanitizer) {
36 EXPECT_DEATH(UseOfUninitializedValue(), "use-of-uninitialized-value");
37}
38#endif
39
40#if defined(ADDRESS_SANITIZER)
41void HeapUseAfterFree() {
Yves Gerey665174f2018-06-19 15:03:05 +020042 char* buf = new char[2];
Oleh Prypin66ca7e32017-09-14 13:05:00 +020043 delete[] buf;
44 buf[0] = buf[1];
45}
46
47TEST(SanitizersDeathTest, AddressSanitizer) {
48 EXPECT_DEATH(HeapUseAfterFree(), "heap-use-after-free");
49}
50#endif
51
52#if defined(UNDEFINED_SANITIZER)
53// For ubsan:
54void SignedIntegerOverflow() {
55 int32_t x = 1234567890;
56 x *= 2;
57}
58
59// For ubsan_vptr:
60struct Base {
61 virtual void f() {}
62 virtual ~Base() {}
63};
Yves Gerey665174f2018-06-19 15:03:05 +020064struct Derived : public Base {};
Oleh Prypin66ca7e32017-09-14 13:05:00 +020065
66void InvalidVptr() {
67 Base b;
68 auto* d = static_cast<Derived*>(&b); // Bad downcast.
69 d->f(); // Virtual function call with object of wrong dynamic type.
70}
71
72TEST(SanitizersDeathTest, UndefinedSanitizer) {
Yves Gerey665174f2018-06-19 15:03:05 +020073 EXPECT_DEATH(
74 {
75 SignedIntegerOverflow();
76 InvalidVptr();
77 },
78 "runtime error");
Oleh Prypin66ca7e32017-09-14 13:05:00 +020079}
80#endif
81
82#if defined(THREAD_SANITIZER)
83class IncrementThread : public Thread {
84 public:
85 explicit IncrementThread(int* value)
Karl Wiberg918f50c2018-07-05 11:40:33 +020086 : Thread(absl::make_unique<NullSocketServer>()), value_(value) {}
Oleh Prypin66ca7e32017-09-14 13:05:00 +020087
88 void Run() override {
89 ++*value_;
90 Thread::Current()->SleepMs(100);
91 }
92
93 // Un-protect Thread::Join for the test.
Yves Gerey665174f2018-06-19 15:03:05 +020094 void Join() { Thread::Join(); }
Oleh Prypin66ca7e32017-09-14 13:05:00 +020095
96 private:
97 int* value_;
98
99 RTC_DISALLOW_COPY_AND_ASSIGN(IncrementThread);
100};
101
102void DataRace() {
103 int value = 0;
104 IncrementThread thread1(&value);
105 IncrementThread thread2(&value);
106 thread1.Start();
107 thread2.Start();
108 thread1.Join();
109 thread2.Join();
110 // TSan seems to mess with gtest's death detection.
111 // Fail intentionally, and rely on detecting the error message.
112 RTC_CHECK(false);
113}
114
115TEST(SanitizersDeathTest, ThreadSanitizer) {
116 EXPECT_DEATH(DataRace(), "data race");
117}
118#endif
119
120} // namespace
121
122} // namespace rtc