1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/message_loop.h"
6 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
7 #include "base/threading/thread.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9
10 namespace base {
11
12 namespace {
13
14 // We use caps here just to ensure that the method name doesn't interfere with
15 // the wildcarded suppressions.
16 class TOOLS_SANITY_TEST_CONCURRENT_THREAD : public PlatformThread::Delegate {
17 public:
TOOLS_SANITY_TEST_CONCURRENT_THREAD(bool * value)18 explicit TOOLS_SANITY_TEST_CONCURRENT_THREAD(bool *value) : value_(value) {}
~TOOLS_SANITY_TEST_CONCURRENT_THREAD()19 ~TOOLS_SANITY_TEST_CONCURRENT_THREAD() {}
ThreadMain()20 void ThreadMain() {
21 *value_ = true;
22
23 // Sleep for a few milliseconds so the two threads are more likely to live
24 // simultaneously. Otherwise we may miss the report due to mutex
25 // lock/unlock's inside thread creation code in pure-happens-before mode...
26 PlatformThread::Sleep(100);
27 }
28 private:
29 bool *value_;
30 };
31
ReadUninitializedValue(char * ptr)32 void ReadUninitializedValue(char *ptr) {
33 if (*ptr == '\0') {
34 (*ptr)++;
35 } else {
36 (*ptr)--;
37 }
38 }
39
ReadValueOutOfArrayBoundsLeft(char * ptr)40 void ReadValueOutOfArrayBoundsLeft(char *ptr) {
41 char c = ptr[-2];
42 VLOG(1) << "Reading a byte out of bounds: " << c;
43 }
44
ReadValueOutOfArrayBoundsRight(char * ptr,size_t size)45 void ReadValueOutOfArrayBoundsRight(char *ptr, size_t size) {
46 char c = ptr[size + 1];
47 VLOG(1) << "Reading a byte out of bounds: " << c;
48 }
49
50 // This is harmless if you run it under Valgrind thanks to redzones.
WriteValueOutOfArrayBoundsLeft(char * ptr)51 void WriteValueOutOfArrayBoundsLeft(char *ptr) {
52 ptr[-1] = 42;
53 }
54
55 // This is harmless if you run it under Valgrind thanks to redzones.
WriteValueOutOfArrayBoundsRight(char * ptr,size_t size)56 void WriteValueOutOfArrayBoundsRight(char *ptr, size_t size) {
57 ptr[size] = 42;
58 }
59
MakeSomeErrors(char * ptr,size_t size)60 void MakeSomeErrors(char *ptr, size_t size) {
61 ReadUninitializedValue(ptr);
62 ReadValueOutOfArrayBoundsLeft(ptr);
63 ReadValueOutOfArrayBoundsRight(ptr, size);
64 WriteValueOutOfArrayBoundsLeft(ptr);
65 WriteValueOutOfArrayBoundsRight(ptr, size);
66 }
67
68 } // namespace
69
70 // A memory leak detector should report an error in this test.
TEST(ToolsSanityTest,MemoryLeak)71 TEST(ToolsSanityTest, MemoryLeak) {
72 int *leak = new int[256]; // Leak some memory intentionally.
73 leak[4] = 1; // Make sure the allocated memory is used.
74 }
75
TEST(ToolsSanityTest,AccessesToNewMemory)76 TEST(ToolsSanityTest, AccessesToNewMemory) {
77 // This test may corrupt memory if not run under Valgrind.
78 if (!RunningOnValgrind())
79 return;
80
81 char *foo = new char[10];
82 MakeSomeErrors(foo, 10);
83 delete [] foo;
84 foo[5] = 0; // Use after delete. This won't break anything under Valgrind.
85 }
86
TEST(ToolsSanityTest,AccessesToMallocMemory)87 TEST(ToolsSanityTest, AccessesToMallocMemory) {
88 // This test may corrupt memory if not run under Valgrind.
89 if (!RunningOnValgrind())
90 return;
91 char *foo = reinterpret_cast<char*>(malloc(10));
92 MakeSomeErrors(foo, 10);
93 free(foo);
94 foo[5] = 0; // Use after free. This won't break anything under Valgrind.
95 }
96
TEST(ToolsSanityTest,ArrayDeletedWithoutBraces)97 TEST(ToolsSanityTest, ArrayDeletedWithoutBraces) {
98 // This test may corrupt memory if not run under Valgrind.
99 if (!RunningOnValgrind())
100 return;
101
102 int *foo = new int[10];
103 delete foo;
104 }
105
TEST(ToolsSanityTest,SingleElementDeletedWithBraces)106 TEST(ToolsSanityTest, SingleElementDeletedWithBraces) {
107 // This test may corrupt memory if not run under Valgrind.
108 if (!RunningOnValgrind())
109 return;
110
111 int *foo = new int;
112 delete [] foo;
113 }
114
115 // A data race detector should report an error in this test.
TEST(ToolsSanityTest,DataRace)116 TEST(ToolsSanityTest, DataRace) {
117 bool shared = false;
118 PlatformThreadHandle a;
119 PlatformThreadHandle b;
120 PlatformThread::Delegate *thread1 =
121 new TOOLS_SANITY_TEST_CONCURRENT_THREAD(&shared);
122 PlatformThread::Delegate *thread2 =
123 new TOOLS_SANITY_TEST_CONCURRENT_THREAD(&shared);
124
125 PlatformThread::Create(0, thread1, &a);
126 PlatformThread::Create(0, thread2, &b);
127 PlatformThread::Join(a);
128 PlatformThread::Join(b);
129 EXPECT_TRUE(shared);
130 delete thread1;
131 delete thread2;
132 }
133
134 } // namespace base
135