| OLD | NEW |
| (Empty) |
| 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 static int* allocateArray() { | |
| 149 // Clang warns about the mismatched new[]/delete if they occur in the same | |
| 150 // function. | |
| 151 return new int[10]; | |
| 152 } | |
| 153 | |
| 154 TEST(ToolsSanityTest, MAYBE_ArrayDeletedWithoutBraces) { | |
| 155 #if !defined(ADDRESS_SANITIZER) && !defined(SYZYASAN) | |
| 156 // This test may corrupt memory if not run under Valgrind or compiled with | |
| 157 // AddressSanitizer. | |
| 158 if (!RunningOnValgrind()) | |
| 159 return; | |
| 160 #endif | |
| 161 | |
| 162 // Without the |volatile|, clang optimizes away the next two lines. | |
| 163 int* volatile foo = allocateArray(); | |
| 164 delete foo; | |
| 165 } | |
| 166 | |
| 167 static int* allocateScalar() { | |
| 168 // Clang warns about the mismatched new/delete[] if they occur in the same | |
| 169 // function. | |
| 170 return new int; | |
| 171 } | |
| 172 | |
| 173 TEST(ToolsSanityTest, MAYBE_SingleElementDeletedWithBraces) { | |
| 174 #if !defined(ADDRESS_SANITIZER) | |
| 175 // This test may corrupt memory if not run under Valgrind or compiled with | |
| 176 // AddressSanitizer. | |
| 177 if (!RunningOnValgrind()) | |
| 178 return; | |
| 179 #endif | |
| 180 | |
| 181 // Without the |volatile|, clang optimizes away the next two lines. | |
| 182 int* volatile foo = allocateScalar(); | |
| 183 (void) foo; | |
| 184 delete [] foo; | |
| 185 } | |
| 186 | |
| 187 #if defined(ADDRESS_SANITIZER) || defined(SYZYASAN) | |
| 188 | |
| 189 TEST(ToolsSanityTest, DISABLED_AddressSanitizerNullDerefCrashTest) { | |
| 190 // Intentionally crash to make sure AddressSanitizer is running. | |
| 191 // This test should not be ran on bots. | |
| 192 int* volatile zero = NULL; | |
| 193 *zero = 0; | |
| 194 } | |
| 195 | |
| 196 TEST(ToolsSanityTest, DISABLED_AddressSanitizerLocalOOBCrashTest) { | |
| 197 // Intentionally crash to make sure AddressSanitizer is instrumenting | |
| 198 // the local variables. | |
| 199 // This test should not be ran on bots. | |
| 200 int array[5]; | |
| 201 // Work around the OOB warning reported by Clang. | |
| 202 int* volatile access = &array[5]; | |
| 203 *access = 43; | |
| 204 } | |
| 205 | |
| 206 namespace { | |
| 207 int g_asan_test_global_array[10]; | |
| 208 } // namespace | |
| 209 | |
| 210 TEST(ToolsSanityTest, DISABLED_AddressSanitizerGlobalOOBCrashTest) { | |
| 211 // Intentionally crash to make sure AddressSanitizer is instrumenting | |
| 212 // the global variables. | |
| 213 // This test should not be ran on bots. | |
| 214 | |
| 215 // Work around the OOB warning reported by Clang. | |
| 216 int* volatile access = g_asan_test_global_array - 1; | |
| 217 *access = 43; | |
| 218 } | |
| 219 | |
| 220 TEST(ToolsSanityTest, AsanHeapOverflow) { | |
| 221 HARMFUL_ACCESS(debug::AsanHeapOverflow() ,"to the right"); | |
| 222 } | |
| 223 | |
| 224 TEST(ToolsSanityTest, AsanHeapUnderflow) { | |
| 225 HARMFUL_ACCESS(debug::AsanHeapUnderflow(), "to the left"); | |
| 226 } | |
| 227 | |
| 228 TEST(ToolsSanityTest, AsanHeapUseAfterFree) { | |
| 229 HARMFUL_ACCESS(debug::AsanHeapUseAfterFree(), "heap-use-after-free"); | |
| 230 } | |
| 231 | |
| 232 #if defined(SYZYASAN) | |
| 233 TEST(ToolsSanityTest, AsanCorruptHeapBlock) { | |
| 234 HARMFUL_ACCESS(debug::AsanCorruptHeapBlock(), ""); | |
| 235 } | |
| 236 | |
| 237 TEST(ToolsSanityTest, AsanCorruptHeap) { | |
| 238 // This test will kill the process by raising an exception, there's no | |
| 239 // particular string to look for in the stack trace. | |
| 240 EXPECT_DEATH(debug::AsanCorruptHeap(), ""); | |
| 241 } | |
| 242 #endif // SYZYASAN | |
| 243 | |
| 244 #endif // ADDRESS_SANITIZER || SYZYASAN | |
| 245 | |
| 246 namespace { | |
| 247 | |
| 248 // We use caps here just to ensure that the method name doesn't interfere with | |
| 249 // the wildcarded suppressions. | |
| 250 class TOOLS_SANITY_TEST_CONCURRENT_THREAD : public PlatformThread::Delegate { | |
| 251 public: | |
| 252 explicit TOOLS_SANITY_TEST_CONCURRENT_THREAD(bool *value) : value_(value) {} | |
| 253 ~TOOLS_SANITY_TEST_CONCURRENT_THREAD() override {} | |
| 254 void ThreadMain() override { | |
| 255 *value_ = true; | |
| 256 | |
| 257 // Sleep for a few milliseconds so the two threads are more likely to live | |
| 258 // simultaneously. Otherwise we may miss the report due to mutex | |
| 259 // lock/unlock's inside thread creation code in pure-happens-before mode... | |
| 260 PlatformThread::Sleep(TimeDelta::FromMilliseconds(100)); | |
| 261 } | |
| 262 private: | |
| 263 bool *value_; | |
| 264 }; | |
| 265 | |
| 266 class ReleaseStoreThread : public PlatformThread::Delegate { | |
| 267 public: | |
| 268 explicit ReleaseStoreThread(base::subtle::Atomic32 *value) : value_(value) {} | |
| 269 ~ReleaseStoreThread() override {} | |
| 270 void ThreadMain() override { | |
| 271 base::subtle::Release_Store(value_, kMagicValue); | |
| 272 | |
| 273 // Sleep for a few milliseconds so the two threads are more likely to live | |
| 274 // simultaneously. Otherwise we may miss the report due to mutex | |
| 275 // lock/unlock's inside thread creation code in pure-happens-before mode... | |
| 276 PlatformThread::Sleep(TimeDelta::FromMilliseconds(100)); | |
| 277 } | |
| 278 private: | |
| 279 base::subtle::Atomic32 *value_; | |
| 280 }; | |
| 281 | |
| 282 class AcquireLoadThread : public PlatformThread::Delegate { | |
| 283 public: | |
| 284 explicit AcquireLoadThread(base::subtle::Atomic32 *value) : value_(value) {} | |
| 285 ~AcquireLoadThread() override {} | |
| 286 void ThreadMain() override { | |
| 287 // Wait for the other thread to make Release_Store | |
| 288 PlatformThread::Sleep(TimeDelta::FromMilliseconds(100)); | |
| 289 base::subtle::Acquire_Load(value_); | |
| 290 } | |
| 291 private: | |
| 292 base::subtle::Atomic32 *value_; | |
| 293 }; | |
| 294 | |
| 295 void RunInParallel(PlatformThread::Delegate *d1, PlatformThread::Delegate *d2) { | |
| 296 PlatformThreadHandle a; | |
| 297 PlatformThreadHandle b; | |
| 298 PlatformThread::Create(0, d1, &a); | |
| 299 PlatformThread::Create(0, d2, &b); | |
| 300 PlatformThread::Join(a); | |
| 301 PlatformThread::Join(b); | |
| 302 } | |
| 303 | |
| 304 #if defined(THREAD_SANITIZER) | |
| 305 void DataRace() { | |
| 306 bool *shared = new bool(false); | |
| 307 TOOLS_SANITY_TEST_CONCURRENT_THREAD thread1(shared), thread2(shared); | |
| 308 RunInParallel(&thread1, &thread2); | |
| 309 EXPECT_TRUE(*shared); | |
| 310 delete shared; | |
| 311 // We're in a death test - crash. | |
| 312 CHECK(0); | |
| 313 } | |
| 314 #endif | |
| 315 | |
| 316 } // namespace | |
| 317 | |
| 318 #if defined(THREAD_SANITIZER) | |
| 319 // A data race detector should report an error in this test. | |
| 320 TEST(ToolsSanityTest, DataRace) { | |
| 321 // The suppression regexp must match that in base/debug/tsan_suppressions.cc. | |
| 322 EXPECT_DEATH(DataRace(), "1 race:base/tools_sanity_unittest.cc"); | |
| 323 } | |
| 324 #endif | |
| 325 | |
| 326 TEST(ToolsSanityTest, AnnotateBenignRace) { | |
| 327 bool shared = false; | |
| 328 ANNOTATE_BENIGN_RACE(&shared, "Intentional race - make sure doesn't show up"); | |
| 329 TOOLS_SANITY_TEST_CONCURRENT_THREAD thread1(&shared), thread2(&shared); | |
| 330 RunInParallel(&thread1, &thread2); | |
| 331 EXPECT_TRUE(shared); | |
| 332 } | |
| 333 | |
| 334 TEST(ToolsSanityTest, AtomicsAreIgnored) { | |
| 335 base::subtle::Atomic32 shared = 0; | |
| 336 ReleaseStoreThread thread1(&shared); | |
| 337 AcquireLoadThread thread2(&shared); | |
| 338 RunInParallel(&thread1, &thread2); | |
| 339 EXPECT_EQ(kMagicValue, shared); | |
| 340 } | |
| 341 | |
| 342 } // namespace base | |
| OLD | NEW |