• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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