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 17namespace base { 18 19namespace { 20 21const 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) \ 34if (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) \ 41do { if (RunningOnValgrind()) { action; } } while (0) 42#endif 43 44void 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 55void 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 64void ReadValueOutOfArrayBoundsLeft(char *ptr) { 65 char c = ptr[-2]; 66 VLOG(1) << "Reading a byte out of bounds: " << c; 67} 68 69void 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. 75void WriteValueOutOfArrayBoundsLeft(char *ptr) { 76 ptr[-1] = kMagicValue; 77} 78 79// This is harmless if you run it under Valgrind thanks to redzones. 80void WriteValueOutOfArrayBoundsRight(char *ptr, size_t size) { 81 ptr[size] = kMagicValue; 82} 83 84void 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. 100TEST(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 132TEST(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 140TEST(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 148TEST(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 161TEST(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 177TEST(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 184TEST(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 194namespace { 195int g_asan_test_global_array[10]; 196} // namespace 197 198TEST(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 208TEST(ToolsSanityTest, AsanHeapOverflow) { 209 HARMFUL_ACCESS(debug::AsanHeapOverflow() ,"to the right"); 210} 211 212TEST(ToolsSanityTest, AsanHeapUnderflow) { 213 HARMFUL_ACCESS(debug::AsanHeapUnderflow(), "to the left"); 214} 215 216TEST(ToolsSanityTest, AsanHeapUseAfterFree) { 217 HARMFUL_ACCESS(debug::AsanHeapUseAfterFree(), "heap-use-after-free"); 218} 219 220#if defined(SYZYASAN) 221TEST(ToolsSanityTest, AsanCorruptHeapBlock) { 222 HARMFUL_ACCESS(debug::AsanCorruptHeapBlock(), ""); 223} 224 225TEST(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 234namespace { 235 236// We use caps here just to ensure that the method name doesn't interfere with 237// the wildcarded suppressions. 238class 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 254class 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 270class 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 283void 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) 293void 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. 308TEST(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 314TEST(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 322TEST(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