xref: /aosp_15_r20/external/webrtc/rtc_tools/sanitizers_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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   (void)x;
59 }
60 
61 // For ubsan_vptr:
62 struct Base {
frtc::__anon606cdf240111::Base63   virtual void f() {}
~Basertc::__anon606cdf240111::Base64   virtual ~Base() {}
65 };
66 struct Derived : public Base {};
67 
InvalidVptr()68 void 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 
TEST(SanitizersDeathTest,UndefinedSanitizer)74 TEST(SanitizersDeathTest, UndefinedSanitizer) {
75   EXPECT_DEATH(
76       {
77         SignedIntegerOverflow();
78         InvalidVptr();
79       },
80       "runtime error");
81 }
82 #endif
83 
84 #if defined(THREAD_SANITIZER)
85 class IncrementThread : public Thread {
86  public:
IncrementThread(int * value)87   explicit IncrementThread(int* value)
88       : Thread(std::make_unique<NullSocketServer>()), value_(value) {}
89 
90   IncrementThread(const IncrementThread&) = delete;
91   IncrementThread& operator=(const IncrementThread&) = delete;
92 
Run()93   void Run() override {
94     ++*value_;
95     Thread::Current()->SleepMs(100);
96   }
97 
98   // Un-protect Thread::Join for the test.
Join()99   void Join() { Thread::Join(); }
100 
101  private:
102   int* value_;
103 };
104 
DataRace()105 void 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.
115   RTC_CHECK_NOTREACHED();
116 }
117 
TEST(SanitizersDeathTest,ThreadSanitizer)118 TEST(SanitizersDeathTest, ThreadSanitizer) {
119   EXPECT_DEATH(DataRace(), "data race");
120 }
121 #endif
122 
123 }  // namespace
124 
125 }  // namespace rtc
126