Home | History | Annotate | Download | only in base
      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