1 // Copyright (c) 2012 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 // This file contains intentional memory errors, some of which may lead to 6 // crashes if the test is ran without special memory testing tools. We use these 7 // errors to verify the sanity of the tools. 8 9 #include "base/atomicops.h" 10 #include "base/message_loop/message_loop.h" 11 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" 12 #include "base/threading/thread.h" 13 #include "testing/gtest/include/gtest/gtest.h" 14 15 namespace base { 16 17 namespace { 18 19 const base::subtle::Atomic32 kMagicValue = 42; 20 21 // Helper for memory accesses that can potentially corrupt memory or cause a 22 // crash during a native run. 23 #if defined(ADDRESS_SANITIZER) 24 #if defined(OS_IOS) 25 // EXPECT_DEATH is not supported on IOS. 26 #define HARMFUL_ACCESS(action,error_regexp) do { action; } while (0) 27 #else 28 #define HARMFUL_ACCESS(action,error_regexp) EXPECT_DEATH(action,error_regexp) 29 #endif // !OS_IOS 30 #else 31 #define HARMFUL_ACCESS(action,error_regexp) \ 32 do { if (RunningOnValgrind()) { action; } } while (0) 33 #endif 34 35 void ReadUninitializedValue(char *ptr) { 36 // Comparison with 64 is to prevent clang from optimizing away the 37 // jump -- valgrind only catches jumps and conditional moves, but clang uses 38 // the borrow flag if the condition is just `*ptr == '\0'`. 39 if (*ptr == 64) { 40 (*ptr)++; 41 } else { 42 (*ptr)--; 43 } 44 } 45 46 void ReadValueOutOfArrayBoundsLeft(char *ptr) { 47 char c = ptr[-2]; 48 VLOG(1) << "Reading a byte out of bounds: " << c; 49 } 50 51 void ReadValueOutOfArrayBoundsRight(char *ptr, size_t size) { 52 char c = ptr[size + 1]; 53 VLOG(1) << "Reading a byte out of bounds: " << c; 54 } 55 56 // This is harmless if you run it under Valgrind thanks to redzones. 57 void WriteValueOutOfArrayBoundsLeft(char *ptr) { 58 ptr[-1] = kMagicValue; 59 } 60 61 // This is harmless if you run it under Valgrind thanks to redzones. 62 void WriteValueOutOfArrayBoundsRight(char *ptr, size_t size) { 63 ptr[size] = kMagicValue; 64 } 65 66 void MakeSomeErrors(char *ptr, size_t size) { 67 ReadUninitializedValue(ptr); 68 HARMFUL_ACCESS(ReadValueOutOfArrayBoundsLeft(ptr), 69 "heap-buffer-overflow.*2 bytes to the left"); 70 HARMFUL_ACCESS(ReadValueOutOfArrayBoundsRight(ptr, size), 71 "heap-buffer-overflow.*1 bytes to the right"); 72 HARMFUL_ACCESS(WriteValueOutOfArrayBoundsLeft(ptr), 73 "heap-buffer-overflow.*1 bytes to the left"); 74 HARMFUL_ACCESS(WriteValueOutOfArrayBoundsRight(ptr, size), 75 "heap-buffer-overflow.*0 bytes to the right"); 76 } 77 78 } // namespace 79 80 // A memory leak detector should report an error in this test. 81 TEST(ToolsSanityTest, MemoryLeak) { 82 // Without the |volatile|, clang optimizes away the next two lines. 83 int* volatile leak = new int[256]; // Leak some memory intentionally. 84 leak[4] = 1; // Make sure the allocated memory is used. 85 } 86 87 #if defined(ADDRESS_SANITIZER) && (defined(OS_IOS) || defined(OS_WIN)) 88 // Because iOS doesn't support death tests, each of the following tests will 89 // crash the whole program under Asan. On Windows Asan is based on SyzyAsan, the 90 // error report mecanism is different than with Asan so those test will fail. 91 #define MAYBE_AccessesToNewMemory DISABLED_AccessesToNewMemory 92 #define MAYBE_AccessesToMallocMemory DISABLED_AccessesToMallocMemory 93 #else 94 #define MAYBE_AccessesToNewMemory AccessesToNewMemory 95 #define MAYBE_AccessesToMallocMemory AccessesToMallocMemory 96 #define MAYBE_ArrayDeletedWithoutBraces ArrayDeletedWithoutBraces 97 #define MAYBE_SingleElementDeletedWithBraces SingleElementDeletedWithBraces 98 #endif 99 100 // The following tests pass with Clang r170392, but not r172454, which 101 // makes AddressSanitizer detect errors in them. We disable these tests under 102 // AddressSanitizer until we fully switch to Clang r172454. After that the 103 // tests should be put back under the (defined(OS_IOS) || defined(OS_WIN)) 104 // clause above. 105 // See also http://crbug.com/172614. 106 #if defined(ADDRESS_SANITIZER) 107 #define MAYBE_SingleElementDeletedWithBraces \ 108 DISABLED_SingleElementDeletedWithBraces 109 #define MAYBE_ArrayDeletedWithoutBraces DISABLED_ArrayDeletedWithoutBraces 110 #endif 111 TEST(ToolsSanityTest, MAYBE_AccessesToNewMemory) { 112 char *foo = new char[10]; 113 MakeSomeErrors(foo, 10); 114 delete [] foo; 115 // Use after delete. 116 HARMFUL_ACCESS(foo[5] = 0, "heap-use-after-free"); 117 } 118 119 TEST(ToolsSanityTest, MAYBE_AccessesToMallocMemory) { 120 char *foo = reinterpret_cast<char*>(malloc(10)); 121 MakeSomeErrors(foo, 10); 122 free(foo); 123 // Use after free. 124 HARMFUL_ACCESS(foo[5] = 0, "heap-use-after-free"); 125 } 126 127 TEST(ToolsSanityTest, MAYBE_ArrayDeletedWithoutBraces) { 128 #if !defined(ADDRESS_SANITIZER) 129 // This test may corrupt memory if not run under Valgrind or compiled with 130 // AddressSanitizer. 131 if (!RunningOnValgrind()) 132 return; 133 #endif 134 135 // Without the |volatile|, clang optimizes away the next two lines. 136 int* volatile foo = new int[10]; 137 delete foo; 138 } 139 140 TEST(ToolsSanityTest, MAYBE_SingleElementDeletedWithBraces) { 141 #if !defined(ADDRESS_SANITIZER) 142 // This test may corrupt memory if not run under Valgrind or compiled with 143 // AddressSanitizer. 144 if (!RunningOnValgrind()) 145 return; 146 #endif 147 148 // Without the |volatile|, clang optimizes away the next two lines. 149 int* volatile foo = new int; 150 (void) foo; 151 delete [] foo; 152 } 153 154 #if defined(ADDRESS_SANITIZER) 155 TEST(ToolsSanityTest, DISABLED_AddressSanitizerNullDerefCrashTest) { 156 // Intentionally crash to make sure AddressSanitizer is running. 157 // This test should not be ran on bots. 158 int* volatile zero = NULL; 159 *zero = 0; 160 } 161 162 TEST(ToolsSanityTest, DISABLED_AddressSanitizerLocalOOBCrashTest) { 163 // Intentionally crash to make sure AddressSanitizer is instrumenting 164 // the local variables. 165 // This test should not be ran on bots. 166 int array[5]; 167 // Work around the OOB warning reported by Clang. 168 int* volatile access = &array[5]; 169 *access = 43; 170 } 171 172 namespace { 173 int g_asan_test_global_array[10]; 174 } // namespace 175 176 TEST(ToolsSanityTest, DISABLED_AddressSanitizerGlobalOOBCrashTest) { 177 // Intentionally crash to make sure AddressSanitizer is instrumenting 178 // the global variables. 179 // This test should not be ran on bots. 180 181 // Work around the OOB warning reported by Clang. 182 int* volatile access = g_asan_test_global_array - 1; 183 *access = 43; 184 } 185 186 #endif 187 188 namespace { 189 190 // We use caps here just to ensure that the method name doesn't interfere with 191 // the wildcarded suppressions. 192 class TOOLS_SANITY_TEST_CONCURRENT_THREAD : public PlatformThread::Delegate { 193 public: 194 explicit TOOLS_SANITY_TEST_CONCURRENT_THREAD(bool *value) : value_(value) {} 195 virtual ~TOOLS_SANITY_TEST_CONCURRENT_THREAD() {} 196 virtual void ThreadMain() OVERRIDE { 197 *value_ = true; 198 199 // Sleep for a few milliseconds so the two threads are more likely to live 200 // simultaneously. Otherwise we may miss the report due to mutex 201 // lock/unlock's inside thread creation code in pure-happens-before mode... 202 PlatformThread::Sleep(TimeDelta::FromMilliseconds(100)); 203 } 204 private: 205 bool *value_; 206 }; 207 208 class ReleaseStoreThread : public PlatformThread::Delegate { 209 public: 210 explicit ReleaseStoreThread(base::subtle::Atomic32 *value) : value_(value) {} 211 virtual ~ReleaseStoreThread() {} 212 virtual void ThreadMain() OVERRIDE { 213 base::subtle::Release_Store(value_, kMagicValue); 214 215 // Sleep for a few milliseconds so the two threads are more likely to live 216 // simultaneously. Otherwise we may miss the report due to mutex 217 // lock/unlock's inside thread creation code in pure-happens-before mode... 218 PlatformThread::Sleep(TimeDelta::FromMilliseconds(100)); 219 } 220 private: 221 base::subtle::Atomic32 *value_; 222 }; 223 224 class AcquireLoadThread : public PlatformThread::Delegate { 225 public: 226 explicit AcquireLoadThread(base::subtle::Atomic32 *value) : value_(value) {} 227 virtual ~AcquireLoadThread() {} 228 virtual void ThreadMain() OVERRIDE { 229 // Wait for the other thread to make Release_Store 230 PlatformThread::Sleep(TimeDelta::FromMilliseconds(100)); 231 base::subtle::Acquire_Load(value_); 232 } 233 private: 234 base::subtle::Atomic32 *value_; 235 }; 236 237 void RunInParallel(PlatformThread::Delegate *d1, PlatformThread::Delegate *d2) { 238 PlatformThreadHandle a; 239 PlatformThreadHandle b; 240 PlatformThread::Create(0, d1, &a); 241 PlatformThread::Create(0, d2, &b); 242 PlatformThread::Join(a); 243 PlatformThread::Join(b); 244 } 245 246 } // namespace 247 248 // A data race detector should report an error in this test. 249 TEST(ToolsSanityTest, DataRace) { 250 bool *shared = new bool(false); 251 TOOLS_SANITY_TEST_CONCURRENT_THREAD thread1(shared), thread2(shared); 252 RunInParallel(&thread1, &thread2); 253 EXPECT_TRUE(*shared); 254 delete shared; 255 } 256 257 TEST(ToolsSanityTest, AnnotateBenignRace) { 258 bool shared = false; 259 ANNOTATE_BENIGN_RACE(&shared, "Intentional race - make sure doesn't show up"); 260 TOOLS_SANITY_TEST_CONCURRENT_THREAD thread1(&shared), thread2(&shared); 261 RunInParallel(&thread1, &thread2); 262 EXPECT_TRUE(shared); 263 } 264 265 TEST(ToolsSanityTest, AtomicsAreIgnored) { 266 base::subtle::Atomic32 shared = 0; 267 ReleaseStoreThread thread1(&shared); 268 AcquireLoadThread thread2(&shared); 269 RunInParallel(&thread1, &thread2); 270 EXPECT_EQ(kMagicValue, shared); 271 } 272 273 } // namespace base 274