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