blob: 6404eb296d76467246268c82c1e1341ab087626b [file] [log] [blame]
Oleh Prypin66ca7e32017-09-14 11:05:001/*
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>
Jonas Olssona4d87372019-07-05 17:08:3313
Mirko Bonadei317a1f02019-09-17 15:06:1814#include <memory>
Oleh Prypin66ca7e32017-09-14 11:05:0015#include <random>
16
Mirko Bonadei92ea95e2017-09-15 04:47:3117#include "rtc_base/checks.h"
Steve Anton10542f22019-01-11 17:11:0018#include "rtc_base/null_socket_server.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3119#include "rtc_base/thread.h"
20#include "test/gtest.h"
Oleh Prypin66ca7e32017-09-14 11:05:0021
22namespace rtc {
23
24namespace {
25
26#if defined(MEMORY_SANITIZER)
27void 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
36TEST(SanitizersDeathTest, MemorySanitizer) {
37 EXPECT_DEATH(UseOfUninitializedValue(), "use-of-uninitialized-value");
38}
39#endif
40
41#if defined(ADDRESS_SANITIZER)
42void HeapUseAfterFree() {
Yves Gerey665174f2018-06-19 13:03:0543 char* buf = new char[2];
Oleh Prypin66ca7e32017-09-14 11:05:0044 delete[] buf;
45 buf[0] = buf[1];
46}
47
48TEST(SanitizersDeathTest, AddressSanitizer) {
49 EXPECT_DEATH(HeapUseAfterFree(), "heap-use-after-free");
50}
51#endif
52
53#if defined(UNDEFINED_SANITIZER)
54// For ubsan:
55void SignedIntegerOverflow() {
56 int32_t x = 1234567890;
57 x *= 2;
Mirko Bonadei32913752021-10-30 15:56:2458 (void)x;
Oleh Prypin66ca7e32017-09-14 11:05:0059}
60
61// For ubsan_vptr:
62struct Base {
63 virtual void f() {}
64 virtual ~Base() {}
65};
Yves Gerey665174f2018-06-19 13:03:0566struct Derived : public Base {};
Oleh Prypin66ca7e32017-09-14 11:05:0067
68void InvalidVptr() {
69 Base b;
70 auto* d = static_cast<Derived*>(&b); // Bad downcast.
71 d->f(); // Virtual function call with object of wrong dynamic type.
72}
73
74TEST(SanitizersDeathTest, UndefinedSanitizer) {
Yves Gerey665174f2018-06-19 13:03:0575 EXPECT_DEATH(
76 {
77 SignedIntegerOverflow();
78 InvalidVptr();
79 },
80 "runtime error");
Oleh Prypin66ca7e32017-09-14 11:05:0081}
82#endif
83
84#if defined(THREAD_SANITIZER)
85class IncrementThread : public Thread {
86 public:
87 explicit IncrementThread(int* value)
Mirko Bonadei317a1f02019-09-17 15:06:1888 : Thread(std::make_unique<NullSocketServer>()), value_(value) {}
Oleh Prypin66ca7e32017-09-14 11:05:0089
Artem Titov6cae2d52022-01-26 15:01:1090 IncrementThread(const IncrementThread&) = delete;
91 IncrementThread& operator=(const IncrementThread&) = delete;
92
Oleh Prypin66ca7e32017-09-14 11:05:0093 void Run() override {
94 ++*value_;
95 Thread::Current()->SleepMs(100);
96 }
97
98 // Un-protect Thread::Join for the test.
Yves Gerey665174f2018-06-19 13:03:0599 void Join() { Thread::Join(); }
Oleh Prypin66ca7e32017-09-14 11:05:00100
101 private:
102 int* value_;
Oleh Prypin66ca7e32017-09-14 11:05:00103};
104
105void DataRace() {
106 int value = 0;
107 IncrementThread thread1(&value);
108 IncrementThread thread2(&value);
109 thread1.Start();
110 thread2.Start();
111 thread1.Join();
112 thread2.Join();
113 // TSan seems to mess with gtest's death detection.
114 // Fail intentionally, and rely on detecting the error message.
Karl Wibergc95b9392020-11-07 23:49:37115 RTC_CHECK_NOTREACHED();
Oleh Prypin66ca7e32017-09-14 11:05:00116}
117
118TEST(SanitizersDeathTest, ThreadSanitizer) {
119 EXPECT_DEATH(DataRace(), "data race");
120}
121#endif
122
123} // namespace
124
125} // namespace rtc