xref: /aosp_15_r20/external/libchrome/base/tools_sanity_unittest.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker //
5*635a8641SAndroid Build Coastguard Worker // This file contains intentional memory errors, some of which may lead to
6*635a8641SAndroid Build Coastguard Worker // crashes if the test is ran without special memory testing tools. We use these
7*635a8641SAndroid Build Coastguard Worker // errors to verify the sanity of the tools.
8*635a8641SAndroid Build Coastguard Worker 
9*635a8641SAndroid Build Coastguard Worker #include <stddef.h>
10*635a8641SAndroid Build Coastguard Worker 
11*635a8641SAndroid Build Coastguard Worker #include "base/atomicops.h"
12*635a8641SAndroid Build Coastguard Worker #include "base/cfi_buildflags.h"
13*635a8641SAndroid Build Coastguard Worker #include "base/debug/asan_invalid_access.h"
14*635a8641SAndroid Build Coastguard Worker #include "base/debug/profiler.h"
15*635a8641SAndroid Build Coastguard Worker #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
16*635a8641SAndroid Build Coastguard Worker #include "base/threading/thread.h"
17*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h"
18*635a8641SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
19*635a8641SAndroid Build Coastguard Worker 
20*635a8641SAndroid Build Coastguard Worker namespace base {
21*635a8641SAndroid Build Coastguard Worker 
22*635a8641SAndroid Build Coastguard Worker namespace {
23*635a8641SAndroid Build Coastguard Worker 
24*635a8641SAndroid Build Coastguard Worker const base::subtle::Atomic32 kMagicValue = 42;
25*635a8641SAndroid Build Coastguard Worker 
26*635a8641SAndroid Build Coastguard Worker // Helper for memory accesses that can potentially corrupt memory or cause a
27*635a8641SAndroid Build Coastguard Worker // crash during a native run.
28*635a8641SAndroid Build Coastguard Worker #if defined(ADDRESS_SANITIZER)
29*635a8641SAndroid Build Coastguard Worker #if defined(OS_IOS)
30*635a8641SAndroid Build Coastguard Worker // EXPECT_DEATH is not supported on IOS.
31*635a8641SAndroid Build Coastguard Worker #define HARMFUL_ACCESS(action,error_regexp) do { action; } while (0)
32*635a8641SAndroid Build Coastguard Worker #else
33*635a8641SAndroid Build Coastguard Worker #define HARMFUL_ACCESS(action,error_regexp) EXPECT_DEATH(action,error_regexp)
34*635a8641SAndroid Build Coastguard Worker #endif  // !OS_IOS
35*635a8641SAndroid Build Coastguard Worker #else
36*635a8641SAndroid Build Coastguard Worker #define HARMFUL_ACCESS(action, error_regexp)
37*635a8641SAndroid Build Coastguard Worker #define HARMFUL_ACCESS_IS_NOOP
38*635a8641SAndroid Build Coastguard Worker #endif
39*635a8641SAndroid Build Coastguard Worker 
DoReadUninitializedValue(char * ptr)40*635a8641SAndroid Build Coastguard Worker void DoReadUninitializedValue(char *ptr) {
41*635a8641SAndroid Build Coastguard Worker   // Comparison with 64 is to prevent clang from optimizing away the
42*635a8641SAndroid Build Coastguard Worker   // jump -- valgrind only catches jumps and conditional moves, but clang uses
43*635a8641SAndroid Build Coastguard Worker   // the borrow flag if the condition is just `*ptr == '\0'`.  We no longer
44*635a8641SAndroid Build Coastguard Worker   // support valgrind, but this constant should be fine to keep as-is.
45*635a8641SAndroid Build Coastguard Worker   if (*ptr == 64) {
46*635a8641SAndroid Build Coastguard Worker     VLOG(1) << "Uninit condition is true";
47*635a8641SAndroid Build Coastguard Worker   } else {
48*635a8641SAndroid Build Coastguard Worker     VLOG(1) << "Uninit condition is false";
49*635a8641SAndroid Build Coastguard Worker   }
50*635a8641SAndroid Build Coastguard Worker }
51*635a8641SAndroid Build Coastguard Worker 
ReadUninitializedValue(char * ptr)52*635a8641SAndroid Build Coastguard Worker void ReadUninitializedValue(char *ptr) {
53*635a8641SAndroid Build Coastguard Worker #if defined(MEMORY_SANITIZER)
54*635a8641SAndroid Build Coastguard Worker   EXPECT_DEATH(DoReadUninitializedValue(ptr),
55*635a8641SAndroid Build Coastguard Worker                "use-of-uninitialized-value");
56*635a8641SAndroid Build Coastguard Worker #else
57*635a8641SAndroid Build Coastguard Worker   DoReadUninitializedValue(ptr);
58*635a8641SAndroid Build Coastguard Worker #endif
59*635a8641SAndroid Build Coastguard Worker }
60*635a8641SAndroid Build Coastguard Worker 
61*635a8641SAndroid Build Coastguard Worker #ifndef HARMFUL_ACCESS_IS_NOOP
ReadValueOutOfArrayBoundsLeft(char * ptr)62*635a8641SAndroid Build Coastguard Worker void ReadValueOutOfArrayBoundsLeft(char *ptr) {
63*635a8641SAndroid Build Coastguard Worker   char c = ptr[-2];
64*635a8641SAndroid Build Coastguard Worker   VLOG(1) << "Reading a byte out of bounds: " << c;
65*635a8641SAndroid Build Coastguard Worker }
66*635a8641SAndroid Build Coastguard Worker 
ReadValueOutOfArrayBoundsRight(char * ptr,size_t size)67*635a8641SAndroid Build Coastguard Worker void ReadValueOutOfArrayBoundsRight(char *ptr, size_t size) {
68*635a8641SAndroid Build Coastguard Worker   char c = ptr[size + 1];
69*635a8641SAndroid Build Coastguard Worker   VLOG(1) << "Reading a byte out of bounds: " << c;
70*635a8641SAndroid Build Coastguard Worker }
71*635a8641SAndroid Build Coastguard Worker 
WriteValueOutOfArrayBoundsLeft(char * ptr)72*635a8641SAndroid Build Coastguard Worker void WriteValueOutOfArrayBoundsLeft(char *ptr) {
73*635a8641SAndroid Build Coastguard Worker   ptr[-1] = kMagicValue;
74*635a8641SAndroid Build Coastguard Worker }
75*635a8641SAndroid Build Coastguard Worker 
WriteValueOutOfArrayBoundsRight(char * ptr,size_t size)76*635a8641SAndroid Build Coastguard Worker void WriteValueOutOfArrayBoundsRight(char *ptr, size_t size) {
77*635a8641SAndroid Build Coastguard Worker   ptr[size] = kMagicValue;
78*635a8641SAndroid Build Coastguard Worker }
79*635a8641SAndroid Build Coastguard Worker #endif  // HARMFUL_ACCESS_IS_NOOP
80*635a8641SAndroid Build Coastguard Worker 
MakeSomeErrors(char * ptr,size_t size)81*635a8641SAndroid Build Coastguard Worker void MakeSomeErrors(char *ptr, size_t size) {
82*635a8641SAndroid Build Coastguard Worker   ReadUninitializedValue(ptr);
83*635a8641SAndroid Build Coastguard Worker 
84*635a8641SAndroid Build Coastguard Worker   HARMFUL_ACCESS(ReadValueOutOfArrayBoundsLeft(ptr),
85*635a8641SAndroid Build Coastguard Worker                  "2 bytes to the left");
86*635a8641SAndroid Build Coastguard Worker   HARMFUL_ACCESS(ReadValueOutOfArrayBoundsRight(ptr, size),
87*635a8641SAndroid Build Coastguard Worker                  "1 bytes to the right");
88*635a8641SAndroid Build Coastguard Worker   HARMFUL_ACCESS(WriteValueOutOfArrayBoundsLeft(ptr),
89*635a8641SAndroid Build Coastguard Worker                  "1 bytes to the left");
90*635a8641SAndroid Build Coastguard Worker   HARMFUL_ACCESS(WriteValueOutOfArrayBoundsRight(ptr, size),
91*635a8641SAndroid Build Coastguard Worker                  "0 bytes to the right");
92*635a8641SAndroid Build Coastguard Worker }
93*635a8641SAndroid Build Coastguard Worker 
94*635a8641SAndroid Build Coastguard Worker }  // namespace
95*635a8641SAndroid Build Coastguard Worker 
96*635a8641SAndroid Build Coastguard Worker // A memory leak detector should report an error in this test.
TEST(ToolsSanityTest,MemoryLeak)97*635a8641SAndroid Build Coastguard Worker TEST(ToolsSanityTest, MemoryLeak) {
98*635a8641SAndroid Build Coastguard Worker   // Without the |volatile|, clang optimizes away the next two lines.
99*635a8641SAndroid Build Coastguard Worker   int* volatile leak = new int[256];  // Leak some memory intentionally.
100*635a8641SAndroid Build Coastguard Worker   leak[4] = 1;  // Make sure the allocated memory is used.
101*635a8641SAndroid Build Coastguard Worker }
102*635a8641SAndroid Build Coastguard Worker 
103*635a8641SAndroid Build Coastguard Worker #if (defined(ADDRESS_SANITIZER) && defined(OS_IOS))
104*635a8641SAndroid Build Coastguard Worker // Because iOS doesn't support death tests, each of the following tests will
105*635a8641SAndroid Build Coastguard Worker // crash the whole program under Asan.
106*635a8641SAndroid Build Coastguard Worker #define MAYBE_AccessesToNewMemory DISABLED_AccessesToNewMemory
107*635a8641SAndroid Build Coastguard Worker #define MAYBE_AccessesToMallocMemory DISABLED_AccessesToMallocMemory
108*635a8641SAndroid Build Coastguard Worker #else
109*635a8641SAndroid Build Coastguard Worker #define MAYBE_AccessesToNewMemory AccessesToNewMemory
110*635a8641SAndroid Build Coastguard Worker #define MAYBE_AccessesToMallocMemory AccessesToMallocMemory
111*635a8641SAndroid Build Coastguard Worker #endif  // (defined(ADDRESS_SANITIZER) && defined(OS_IOS))
112*635a8641SAndroid Build Coastguard Worker 
113*635a8641SAndroid Build Coastguard Worker // The following tests pass with Clang r170392, but not r172454, which
114*635a8641SAndroid Build Coastguard Worker // makes AddressSanitizer detect errors in them. We disable these tests under
115*635a8641SAndroid Build Coastguard Worker // AddressSanitizer until we fully switch to Clang r172454. After that the
116*635a8641SAndroid Build Coastguard Worker // tests should be put back under the (defined(OS_IOS) || defined(OS_WIN))
117*635a8641SAndroid Build Coastguard Worker // clause above.
118*635a8641SAndroid Build Coastguard Worker // See also http://crbug.com/172614.
119*635a8641SAndroid Build Coastguard Worker #if defined(ADDRESS_SANITIZER)
120*635a8641SAndroid Build Coastguard Worker #define MAYBE_SingleElementDeletedWithBraces \
121*635a8641SAndroid Build Coastguard Worker     DISABLED_SingleElementDeletedWithBraces
122*635a8641SAndroid Build Coastguard Worker #define MAYBE_ArrayDeletedWithoutBraces DISABLED_ArrayDeletedWithoutBraces
123*635a8641SAndroid Build Coastguard Worker #else
124*635a8641SAndroid Build Coastguard Worker #define MAYBE_ArrayDeletedWithoutBraces ArrayDeletedWithoutBraces
125*635a8641SAndroid Build Coastguard Worker #define MAYBE_SingleElementDeletedWithBraces SingleElementDeletedWithBraces
126*635a8641SAndroid Build Coastguard Worker #endif  // defined(ADDRESS_SANITIZER)
127*635a8641SAndroid Build Coastguard Worker 
TEST(ToolsSanityTest,MAYBE_AccessesToNewMemory)128*635a8641SAndroid Build Coastguard Worker TEST(ToolsSanityTest, MAYBE_AccessesToNewMemory) {
129*635a8641SAndroid Build Coastguard Worker   char *foo = new char[10];
130*635a8641SAndroid Build Coastguard Worker   MakeSomeErrors(foo, 10);
131*635a8641SAndroid Build Coastguard Worker   delete [] foo;
132*635a8641SAndroid Build Coastguard Worker   // Use after delete.
133*635a8641SAndroid Build Coastguard Worker   HARMFUL_ACCESS(foo[5] = 0, "heap-use-after-free");
134*635a8641SAndroid Build Coastguard Worker }
135*635a8641SAndroid Build Coastguard Worker 
TEST(ToolsSanityTest,MAYBE_AccessesToMallocMemory)136*635a8641SAndroid Build Coastguard Worker TEST(ToolsSanityTest, MAYBE_AccessesToMallocMemory) {
137*635a8641SAndroid Build Coastguard Worker   char *foo = reinterpret_cast<char*>(malloc(10));
138*635a8641SAndroid Build Coastguard Worker   MakeSomeErrors(foo, 10);
139*635a8641SAndroid Build Coastguard Worker   free(foo);
140*635a8641SAndroid Build Coastguard Worker   // Use after free.
141*635a8641SAndroid Build Coastguard Worker   HARMFUL_ACCESS(foo[5] = 0, "heap-use-after-free");
142*635a8641SAndroid Build Coastguard Worker }
143*635a8641SAndroid Build Coastguard Worker 
144*635a8641SAndroid Build Coastguard Worker #if defined(ADDRESS_SANITIZER)
145*635a8641SAndroid Build Coastguard Worker 
allocateArray()146*635a8641SAndroid Build Coastguard Worker static int* allocateArray() {
147*635a8641SAndroid Build Coastguard Worker   // Clang warns about the mismatched new[]/delete if they occur in the same
148*635a8641SAndroid Build Coastguard Worker   // function.
149*635a8641SAndroid Build Coastguard Worker   return new int[10];
150*635a8641SAndroid Build Coastguard Worker }
151*635a8641SAndroid Build Coastguard Worker 
152*635a8641SAndroid Build Coastguard Worker // This test may corrupt memory if not compiled with AddressSanitizer.
TEST(ToolsSanityTest,MAYBE_ArrayDeletedWithoutBraces)153*635a8641SAndroid Build Coastguard Worker TEST(ToolsSanityTest, MAYBE_ArrayDeletedWithoutBraces) {
154*635a8641SAndroid Build Coastguard Worker   // Without the |volatile|, clang optimizes away the next two lines.
155*635a8641SAndroid Build Coastguard Worker   int* volatile foo = allocateArray();
156*635a8641SAndroid Build Coastguard Worker   delete foo;
157*635a8641SAndroid Build Coastguard Worker }
158*635a8641SAndroid Build Coastguard Worker #endif
159*635a8641SAndroid Build Coastguard Worker 
160*635a8641SAndroid Build Coastguard Worker #if defined(ADDRESS_SANITIZER)
allocateScalar()161*635a8641SAndroid Build Coastguard Worker static int* allocateScalar() {
162*635a8641SAndroid Build Coastguard Worker   // Clang warns about the mismatched new/delete[] if they occur in the same
163*635a8641SAndroid Build Coastguard Worker   // function.
164*635a8641SAndroid Build Coastguard Worker   return new int;
165*635a8641SAndroid Build Coastguard Worker }
166*635a8641SAndroid Build Coastguard Worker 
167*635a8641SAndroid Build Coastguard Worker // This test may corrupt memory if not compiled with AddressSanitizer.
TEST(ToolsSanityTest,MAYBE_SingleElementDeletedWithBraces)168*635a8641SAndroid Build Coastguard Worker TEST(ToolsSanityTest, MAYBE_SingleElementDeletedWithBraces) {
169*635a8641SAndroid Build Coastguard Worker   // Without the |volatile|, clang optimizes away the next two lines.
170*635a8641SAndroid Build Coastguard Worker   int* volatile foo = allocateScalar();
171*635a8641SAndroid Build Coastguard Worker   (void) foo;
172*635a8641SAndroid Build Coastguard Worker   delete [] foo;
173*635a8641SAndroid Build Coastguard Worker }
174*635a8641SAndroid Build Coastguard Worker #endif
175*635a8641SAndroid Build Coastguard Worker 
176*635a8641SAndroid Build Coastguard Worker #if defined(ADDRESS_SANITIZER)
177*635a8641SAndroid Build Coastguard Worker 
TEST(ToolsSanityTest,DISABLED_AddressSanitizerNullDerefCrashTest)178*635a8641SAndroid Build Coastguard Worker TEST(ToolsSanityTest, DISABLED_AddressSanitizerNullDerefCrashTest) {
179*635a8641SAndroid Build Coastguard Worker   // Intentionally crash to make sure AddressSanitizer is running.
180*635a8641SAndroid Build Coastguard Worker   // This test should not be ran on bots.
181*635a8641SAndroid Build Coastguard Worker   int* volatile zero = NULL;
182*635a8641SAndroid Build Coastguard Worker   *zero = 0;
183*635a8641SAndroid Build Coastguard Worker }
184*635a8641SAndroid Build Coastguard Worker 
TEST(ToolsSanityTest,DISABLED_AddressSanitizerLocalOOBCrashTest)185*635a8641SAndroid Build Coastguard Worker TEST(ToolsSanityTest, DISABLED_AddressSanitizerLocalOOBCrashTest) {
186*635a8641SAndroid Build Coastguard Worker   // Intentionally crash to make sure AddressSanitizer is instrumenting
187*635a8641SAndroid Build Coastguard Worker   // the local variables.
188*635a8641SAndroid Build Coastguard Worker   // This test should not be ran on bots.
189*635a8641SAndroid Build Coastguard Worker   int array[5];
190*635a8641SAndroid Build Coastguard Worker   // Work around the OOB warning reported by Clang.
191*635a8641SAndroid Build Coastguard Worker   int* volatile access = &array[5];
192*635a8641SAndroid Build Coastguard Worker   *access = 43;
193*635a8641SAndroid Build Coastguard Worker }
194*635a8641SAndroid Build Coastguard Worker 
195*635a8641SAndroid Build Coastguard Worker namespace {
196*635a8641SAndroid Build Coastguard Worker int g_asan_test_global_array[10];
197*635a8641SAndroid Build Coastguard Worker }  // namespace
198*635a8641SAndroid Build Coastguard Worker 
TEST(ToolsSanityTest,DISABLED_AddressSanitizerGlobalOOBCrashTest)199*635a8641SAndroid Build Coastguard Worker TEST(ToolsSanityTest, DISABLED_AddressSanitizerGlobalOOBCrashTest) {
200*635a8641SAndroid Build Coastguard Worker   // Intentionally crash to make sure AddressSanitizer is instrumenting
201*635a8641SAndroid Build Coastguard Worker   // the global variables.
202*635a8641SAndroid Build Coastguard Worker   // This test should not be ran on bots.
203*635a8641SAndroid Build Coastguard Worker 
204*635a8641SAndroid Build Coastguard Worker   // Work around the OOB warning reported by Clang.
205*635a8641SAndroid Build Coastguard Worker   int* volatile access = g_asan_test_global_array - 1;
206*635a8641SAndroid Build Coastguard Worker   *access = 43;
207*635a8641SAndroid Build Coastguard Worker }
208*635a8641SAndroid Build Coastguard Worker 
209*635a8641SAndroid Build Coastguard Worker #ifndef HARMFUL_ACCESS_IS_NOOP
TEST(ToolsSanityTest,AsanHeapOverflow)210*635a8641SAndroid Build Coastguard Worker TEST(ToolsSanityTest, AsanHeapOverflow) {
211*635a8641SAndroid Build Coastguard Worker   HARMFUL_ACCESS(debug::AsanHeapOverflow() ,"to the right");
212*635a8641SAndroid Build Coastguard Worker }
213*635a8641SAndroid Build Coastguard Worker 
TEST(ToolsSanityTest,AsanHeapUnderflow)214*635a8641SAndroid Build Coastguard Worker TEST(ToolsSanityTest, AsanHeapUnderflow) {
215*635a8641SAndroid Build Coastguard Worker   HARMFUL_ACCESS(debug::AsanHeapUnderflow(), "to the left");
216*635a8641SAndroid Build Coastguard Worker }
217*635a8641SAndroid Build Coastguard Worker 
TEST(ToolsSanityTest,AsanHeapUseAfterFree)218*635a8641SAndroid Build Coastguard Worker TEST(ToolsSanityTest, AsanHeapUseAfterFree) {
219*635a8641SAndroid Build Coastguard Worker   HARMFUL_ACCESS(debug::AsanHeapUseAfterFree(), "heap-use-after-free");
220*635a8641SAndroid Build Coastguard Worker }
221*635a8641SAndroid Build Coastguard Worker 
222*635a8641SAndroid Build Coastguard Worker #if defined(OS_WIN)
223*635a8641SAndroid Build Coastguard Worker // The ASAN runtime doesn't detect heap corruption, this needs fixing before
224*635a8641SAndroid Build Coastguard Worker // ASAN builds can ship to the wild. See https://crbug.com/818747.
TEST(ToolsSanityTest,DISABLED_AsanCorruptHeapBlock)225*635a8641SAndroid Build Coastguard Worker TEST(ToolsSanityTest, DISABLED_AsanCorruptHeapBlock) {
226*635a8641SAndroid Build Coastguard Worker   HARMFUL_ACCESS(debug::AsanCorruptHeapBlock(), "");
227*635a8641SAndroid Build Coastguard Worker }
228*635a8641SAndroid Build Coastguard Worker 
TEST(ToolsSanityTest,DISABLED_AsanCorruptHeap)229*635a8641SAndroid Build Coastguard Worker TEST(ToolsSanityTest, DISABLED_AsanCorruptHeap) {
230*635a8641SAndroid Build Coastguard Worker   // This test will kill the process by raising an exception, there's no
231*635a8641SAndroid Build Coastguard Worker   // particular string to look for in the stack trace.
232*635a8641SAndroid Build Coastguard Worker   EXPECT_DEATH(debug::AsanCorruptHeap(), "");
233*635a8641SAndroid Build Coastguard Worker }
234*635a8641SAndroid Build Coastguard Worker #endif  // OS_WIN
235*635a8641SAndroid Build Coastguard Worker #endif  // !HARMFUL_ACCESS_IS_NOOP
236*635a8641SAndroid Build Coastguard Worker 
237*635a8641SAndroid Build Coastguard Worker #endif  // ADDRESS_SANITIZER
238*635a8641SAndroid Build Coastguard Worker 
239*635a8641SAndroid Build Coastguard Worker namespace {
240*635a8641SAndroid Build Coastguard Worker 
241*635a8641SAndroid Build Coastguard Worker // We use caps here just to ensure that the method name doesn't interfere with
242*635a8641SAndroid Build Coastguard Worker // the wildcarded suppressions.
243*635a8641SAndroid Build Coastguard Worker class TOOLS_SANITY_TEST_CONCURRENT_THREAD : public PlatformThread::Delegate {
244*635a8641SAndroid Build Coastguard Worker  public:
TOOLS_SANITY_TEST_CONCURRENT_THREAD(bool * value)245*635a8641SAndroid Build Coastguard Worker   explicit TOOLS_SANITY_TEST_CONCURRENT_THREAD(bool *value) : value_(value) {}
246*635a8641SAndroid Build Coastguard Worker   ~TOOLS_SANITY_TEST_CONCURRENT_THREAD() override = default;
ThreadMain()247*635a8641SAndroid Build Coastguard Worker   void ThreadMain() override {
248*635a8641SAndroid Build Coastguard Worker     *value_ = true;
249*635a8641SAndroid Build Coastguard Worker 
250*635a8641SAndroid Build Coastguard Worker     // Sleep for a few milliseconds so the two threads are more likely to live
251*635a8641SAndroid Build Coastguard Worker     // simultaneously. Otherwise we may miss the report due to mutex
252*635a8641SAndroid Build Coastguard Worker     // lock/unlock's inside thread creation code in pure-happens-before mode...
253*635a8641SAndroid Build Coastguard Worker     PlatformThread::Sleep(TimeDelta::FromMilliseconds(100));
254*635a8641SAndroid Build Coastguard Worker   }
255*635a8641SAndroid Build Coastguard Worker  private:
256*635a8641SAndroid Build Coastguard Worker   bool *value_;
257*635a8641SAndroid Build Coastguard Worker };
258*635a8641SAndroid Build Coastguard Worker 
259*635a8641SAndroid Build Coastguard Worker class ReleaseStoreThread : public PlatformThread::Delegate {
260*635a8641SAndroid Build Coastguard Worker  public:
ReleaseStoreThread(base::subtle::Atomic32 * value)261*635a8641SAndroid Build Coastguard Worker   explicit ReleaseStoreThread(base::subtle::Atomic32 *value) : value_(value) {}
262*635a8641SAndroid Build Coastguard Worker   ~ReleaseStoreThread() override = default;
ThreadMain()263*635a8641SAndroid Build Coastguard Worker   void ThreadMain() override {
264*635a8641SAndroid Build Coastguard Worker     base::subtle::Release_Store(value_, kMagicValue);
265*635a8641SAndroid Build Coastguard Worker 
266*635a8641SAndroid Build Coastguard Worker     // Sleep for a few milliseconds so the two threads are more likely to live
267*635a8641SAndroid Build Coastguard Worker     // simultaneously. Otherwise we may miss the report due to mutex
268*635a8641SAndroid Build Coastguard Worker     // lock/unlock's inside thread creation code in pure-happens-before mode...
269*635a8641SAndroid Build Coastguard Worker     PlatformThread::Sleep(TimeDelta::FromMilliseconds(100));
270*635a8641SAndroid Build Coastguard Worker   }
271*635a8641SAndroid Build Coastguard Worker  private:
272*635a8641SAndroid Build Coastguard Worker   base::subtle::Atomic32 *value_;
273*635a8641SAndroid Build Coastguard Worker };
274*635a8641SAndroid Build Coastguard Worker 
275*635a8641SAndroid Build Coastguard Worker class AcquireLoadThread : public PlatformThread::Delegate {
276*635a8641SAndroid Build Coastguard Worker  public:
AcquireLoadThread(base::subtle::Atomic32 * value)277*635a8641SAndroid Build Coastguard Worker   explicit AcquireLoadThread(base::subtle::Atomic32 *value) : value_(value) {}
278*635a8641SAndroid Build Coastguard Worker   ~AcquireLoadThread() override = default;
ThreadMain()279*635a8641SAndroid Build Coastguard Worker   void ThreadMain() override {
280*635a8641SAndroid Build Coastguard Worker     // Wait for the other thread to make Release_Store
281*635a8641SAndroid Build Coastguard Worker     PlatformThread::Sleep(TimeDelta::FromMilliseconds(100));
282*635a8641SAndroid Build Coastguard Worker     base::subtle::Acquire_Load(value_);
283*635a8641SAndroid Build Coastguard Worker   }
284*635a8641SAndroid Build Coastguard Worker  private:
285*635a8641SAndroid Build Coastguard Worker   base::subtle::Atomic32 *value_;
286*635a8641SAndroid Build Coastguard Worker };
287*635a8641SAndroid Build Coastguard Worker 
RunInParallel(PlatformThread::Delegate * d1,PlatformThread::Delegate * d2)288*635a8641SAndroid Build Coastguard Worker void RunInParallel(PlatformThread::Delegate *d1, PlatformThread::Delegate *d2) {
289*635a8641SAndroid Build Coastguard Worker   PlatformThreadHandle a;
290*635a8641SAndroid Build Coastguard Worker   PlatformThreadHandle b;
291*635a8641SAndroid Build Coastguard Worker   PlatformThread::Create(0, d1, &a);
292*635a8641SAndroid Build Coastguard Worker   PlatformThread::Create(0, d2, &b);
293*635a8641SAndroid Build Coastguard Worker   PlatformThread::Join(a);
294*635a8641SAndroid Build Coastguard Worker   PlatformThread::Join(b);
295*635a8641SAndroid Build Coastguard Worker }
296*635a8641SAndroid Build Coastguard Worker 
297*635a8641SAndroid Build Coastguard Worker #if defined(THREAD_SANITIZER)
DataRace()298*635a8641SAndroid Build Coastguard Worker void DataRace() {
299*635a8641SAndroid Build Coastguard Worker   bool *shared = new bool(false);
300*635a8641SAndroid Build Coastguard Worker   TOOLS_SANITY_TEST_CONCURRENT_THREAD thread1(shared), thread2(shared);
301*635a8641SAndroid Build Coastguard Worker   RunInParallel(&thread1, &thread2);
302*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(*shared);
303*635a8641SAndroid Build Coastguard Worker   delete shared;
304*635a8641SAndroid Build Coastguard Worker   // We're in a death test - crash.
305*635a8641SAndroid Build Coastguard Worker   CHECK(0);
306*635a8641SAndroid Build Coastguard Worker }
307*635a8641SAndroid Build Coastguard Worker #endif
308*635a8641SAndroid Build Coastguard Worker 
309*635a8641SAndroid Build Coastguard Worker }  // namespace
310*635a8641SAndroid Build Coastguard Worker 
311*635a8641SAndroid Build Coastguard Worker #if defined(THREAD_SANITIZER)
312*635a8641SAndroid Build Coastguard Worker // A data race detector should report an error in this test.
TEST(ToolsSanityTest,DataRace)313*635a8641SAndroid Build Coastguard Worker TEST(ToolsSanityTest, DataRace) {
314*635a8641SAndroid Build Coastguard Worker   // The suppression regexp must match that in base/debug/tsan_suppressions.cc.
315*635a8641SAndroid Build Coastguard Worker   EXPECT_DEATH(DataRace(), "1 race:base/tools_sanity_unittest.cc");
316*635a8641SAndroid Build Coastguard Worker }
317*635a8641SAndroid Build Coastguard Worker #endif
318*635a8641SAndroid Build Coastguard Worker 
TEST(ToolsSanityTest,AnnotateBenignRace)319*635a8641SAndroid Build Coastguard Worker TEST(ToolsSanityTest, AnnotateBenignRace) {
320*635a8641SAndroid Build Coastguard Worker   bool shared = false;
321*635a8641SAndroid Build Coastguard Worker   ANNOTATE_BENIGN_RACE(&shared, "Intentional race - make sure doesn't show up");
322*635a8641SAndroid Build Coastguard Worker   TOOLS_SANITY_TEST_CONCURRENT_THREAD thread1(&shared), thread2(&shared);
323*635a8641SAndroid Build Coastguard Worker   RunInParallel(&thread1, &thread2);
324*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(shared);
325*635a8641SAndroid Build Coastguard Worker }
326*635a8641SAndroid Build Coastguard Worker 
TEST(ToolsSanityTest,AtomicsAreIgnored)327*635a8641SAndroid Build Coastguard Worker TEST(ToolsSanityTest, AtomicsAreIgnored) {
328*635a8641SAndroid Build Coastguard Worker   base::subtle::Atomic32 shared = 0;
329*635a8641SAndroid Build Coastguard Worker   ReleaseStoreThread thread1(&shared);
330*635a8641SAndroid Build Coastguard Worker   AcquireLoadThread thread2(&shared);
331*635a8641SAndroid Build Coastguard Worker   RunInParallel(&thread1, &thread2);
332*635a8641SAndroid Build Coastguard Worker   EXPECT_EQ(kMagicValue, shared);
333*635a8641SAndroid Build Coastguard Worker }
334*635a8641SAndroid Build Coastguard Worker 
335*635a8641SAndroid Build Coastguard Worker #if BUILDFLAG(CFI_ENFORCEMENT_TRAP)
336*635a8641SAndroid Build Coastguard Worker #if defined(OS_WIN)
337*635a8641SAndroid Build Coastguard Worker #define CFI_ERROR_MSG "EXCEPTION_ILLEGAL_INSTRUCTION"
338*635a8641SAndroid Build Coastguard Worker #elif defined(OS_ANDROID)
339*635a8641SAndroid Build Coastguard Worker // TODO(pcc): Produce proper stack dumps on Android and test for the correct
340*635a8641SAndroid Build Coastguard Worker // si_code here.
341*635a8641SAndroid Build Coastguard Worker #define CFI_ERROR_MSG "^$"
342*635a8641SAndroid Build Coastguard Worker #else
343*635a8641SAndroid Build Coastguard Worker #define CFI_ERROR_MSG "ILL_ILLOPN"
344*635a8641SAndroid Build Coastguard Worker #endif
345*635a8641SAndroid Build Coastguard Worker #elif BUILDFLAG(CFI_ENFORCEMENT_DIAGNOSTIC)
346*635a8641SAndroid Build Coastguard Worker #define CFI_ERROR_MSG "runtime error: control flow integrity check"
347*635a8641SAndroid Build Coastguard Worker #endif  // BUILDFLAG(CFI_ENFORCEMENT_TRAP || CFI_ENFORCEMENT_DIAGNOSTIC)
348*635a8641SAndroid Build Coastguard Worker 
349*635a8641SAndroid Build Coastguard Worker #if defined(CFI_ERROR_MSG)
350*635a8641SAndroid Build Coastguard Worker class A {
351*635a8641SAndroid Build Coastguard Worker  public:
A()352*635a8641SAndroid Build Coastguard Worker   A(): n_(0) {}
f()353*635a8641SAndroid Build Coastguard Worker   virtual void f() { n_++; }
354*635a8641SAndroid Build Coastguard Worker  protected:
355*635a8641SAndroid Build Coastguard Worker   int n_;
356*635a8641SAndroid Build Coastguard Worker };
357*635a8641SAndroid Build Coastguard Worker 
358*635a8641SAndroid Build Coastguard Worker class B: public A {
359*635a8641SAndroid Build Coastguard Worker  public:
f()360*635a8641SAndroid Build Coastguard Worker   void f() override { n_--; }
361*635a8641SAndroid Build Coastguard Worker };
362*635a8641SAndroid Build Coastguard Worker 
363*635a8641SAndroid Build Coastguard Worker class C: public B {
364*635a8641SAndroid Build Coastguard Worker  public:
f()365*635a8641SAndroid Build Coastguard Worker   void f() override { n_ += 2; }
366*635a8641SAndroid Build Coastguard Worker };
367*635a8641SAndroid Build Coastguard Worker 
KillVptrAndCall(A * obj)368*635a8641SAndroid Build Coastguard Worker NOINLINE void KillVptrAndCall(A *obj) {
369*635a8641SAndroid Build Coastguard Worker   *reinterpret_cast<void **>(obj) = 0;
370*635a8641SAndroid Build Coastguard Worker   obj->f();
371*635a8641SAndroid Build Coastguard Worker }
372*635a8641SAndroid Build Coastguard Worker 
TEST(ToolsSanityTest,BadVirtualCallNull)373*635a8641SAndroid Build Coastguard Worker TEST(ToolsSanityTest, BadVirtualCallNull) {
374*635a8641SAndroid Build Coastguard Worker   A a;
375*635a8641SAndroid Build Coastguard Worker   B b;
376*635a8641SAndroid Build Coastguard Worker   EXPECT_DEATH({ KillVptrAndCall(&a); KillVptrAndCall(&b); }, CFI_ERROR_MSG);
377*635a8641SAndroid Build Coastguard Worker }
378*635a8641SAndroid Build Coastguard Worker 
OverwriteVptrAndCall(B * obj,A * vptr)379*635a8641SAndroid Build Coastguard Worker NOINLINE void OverwriteVptrAndCall(B *obj, A *vptr) {
380*635a8641SAndroid Build Coastguard Worker   *reinterpret_cast<void **>(obj) = *reinterpret_cast<void **>(vptr);
381*635a8641SAndroid Build Coastguard Worker   obj->f();
382*635a8641SAndroid Build Coastguard Worker }
383*635a8641SAndroid Build Coastguard Worker 
TEST(ToolsSanityTest,BadVirtualCallWrongType)384*635a8641SAndroid Build Coastguard Worker TEST(ToolsSanityTest, BadVirtualCallWrongType) {
385*635a8641SAndroid Build Coastguard Worker   A a;
386*635a8641SAndroid Build Coastguard Worker   B b;
387*635a8641SAndroid Build Coastguard Worker   C c;
388*635a8641SAndroid Build Coastguard Worker   EXPECT_DEATH({ OverwriteVptrAndCall(&b, &a); OverwriteVptrAndCall(&b, &c); },
389*635a8641SAndroid Build Coastguard Worker                CFI_ERROR_MSG);
390*635a8641SAndroid Build Coastguard Worker }
391*635a8641SAndroid Build Coastguard Worker 
392*635a8641SAndroid Build Coastguard Worker // TODO(pcc): remove CFI_CAST_CHECK, see https://crbug.com/626794.
393*635a8641SAndroid Build Coastguard Worker #if BUILDFLAG(CFI_CAST_CHECK)
TEST(ToolsSanityTest,BadDerivedCast)394*635a8641SAndroid Build Coastguard Worker TEST(ToolsSanityTest, BadDerivedCast) {
395*635a8641SAndroid Build Coastguard Worker   A a;
396*635a8641SAndroid Build Coastguard Worker   EXPECT_DEATH((void)(B*)&a, CFI_ERROR_MSG);
397*635a8641SAndroid Build Coastguard Worker }
398*635a8641SAndroid Build Coastguard Worker 
TEST(ToolsSanityTest,BadUnrelatedCast)399*635a8641SAndroid Build Coastguard Worker TEST(ToolsSanityTest, BadUnrelatedCast) {
400*635a8641SAndroid Build Coastguard Worker   class A {
401*635a8641SAndroid Build Coastguard Worker     virtual void f() {}
402*635a8641SAndroid Build Coastguard Worker   };
403*635a8641SAndroid Build Coastguard Worker 
404*635a8641SAndroid Build Coastguard Worker   class B {
405*635a8641SAndroid Build Coastguard Worker     virtual void f() {}
406*635a8641SAndroid Build Coastguard Worker   };
407*635a8641SAndroid Build Coastguard Worker 
408*635a8641SAndroid Build Coastguard Worker   A a;
409*635a8641SAndroid Build Coastguard Worker   EXPECT_DEATH((void)(B*)&a, CFI_ERROR_MSG);
410*635a8641SAndroid Build Coastguard Worker }
411*635a8641SAndroid Build Coastguard Worker #endif  // BUILDFLAG(CFI_CAST_CHECK)
412*635a8641SAndroid Build Coastguard Worker 
413*635a8641SAndroid Build Coastguard Worker #endif  // CFI_ERROR_MSG
414*635a8641SAndroid Build Coastguard Worker 
415*635a8641SAndroid Build Coastguard Worker #undef CFI_ERROR_MSG
416*635a8641SAndroid Build Coastguard Worker #undef MAYBE_AccessesToNewMemory
417*635a8641SAndroid Build Coastguard Worker #undef MAYBE_AccessesToMallocMemory
418*635a8641SAndroid Build Coastguard Worker #undef MAYBE_ArrayDeletedWithoutBraces
419*635a8641SAndroid Build Coastguard Worker #undef MAYBE_SingleElementDeletedWithBraces
420*635a8641SAndroid Build Coastguard Worker #undef HARMFUL_ACCESS
421*635a8641SAndroid Build Coastguard Worker #undef HARMFUL_ACCESS_IS_NOOP
422*635a8641SAndroid Build Coastguard Worker 
423*635a8641SAndroid Build Coastguard Worker }  // namespace base
424