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/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