Home | History | Annotate | Download | only in debug
      1 // Copyright 2014 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 #if defined(OS_WIN)
      6 #include <windows.h>
      7 #endif
      8 
      9 #include "base/debug/alias.h"
     10 #include "base/debug/asan_invalid_access.h"
     11 #include "base/logging.h"
     12 #include "base/memory/scoped_ptr.h"
     13 
     14 namespace base {
     15 namespace debug {
     16 
     17 namespace {
     18 
     19 #if defined(SYZYASAN) && defined(COMPILER_MSVC)
     20 // Disable warning C4530: "C++ exception handler used, but unwind semantics are
     21 // not enabled". We don't want to change the compilation flags just for this
     22 // test, and no exception should be triggered here, so this warning has no value
     23 // here.
     24 #pragma warning(push)
     25 #pragma warning(disable: 4530)
     26 // Corrupt a memory block and make sure that the corruption gets detected either
     27 // when we free it or when another crash happens (if |induce_crash| is set to
     28 // true).
     29 NOINLINE void CorruptMemoryBlock(bool induce_crash) {
     30   // NOTE(sebmarchand): We intentionally corrupt a memory block here in order to
     31   //     trigger an Address Sanitizer (ASAN) error report.
     32   static const int kArraySize = 5;
     33   int* array = new int[kArraySize];
     34   // Encapsulate the invalid memory access into a try-catch statement to prevent
     35   // this function from being instrumented. This way the underflow won't be
     36   // detected but the corruption will (as the allocator will still be hooked).
     37   try {
     38     // Declares the dummy value as volatile to make sure it doesn't get
     39     // optimized away.
     40     int volatile dummy = array[-1]--;
     41     base::debug::Alias(const_cast<int*>(&dummy));
     42   } catch (...) {
     43   }
     44   if (induce_crash)
     45     CHECK(false);
     46   delete[] array;
     47 }
     48 #pragma warning(pop)
     49 #endif  // SYZYASAN && COMPILER_MSVC
     50 
     51 }  // namespace
     52 
     53 #if defined(ADDRESS_SANITIZER) || defined(SYZYASAN)
     54 // NOTE(sebmarchand): We intentionally perform some invalid heap access here in
     55 //     order to trigger an AddressSanitizer (ASan) error report.
     56 
     57 static const size_t kArraySize = 5;
     58 
     59 void AsanHeapOverflow() {
     60   scoped_ptr<int[]> array(new int[kArraySize]);
     61   // Declares the dummy value as volatile to make sure it doesn't get optimized
     62   // away.
     63   int volatile dummy = 0;
     64   dummy = array[kArraySize];
     65   base::debug::Alias(const_cast<int*>(&dummy));
     66 }
     67 
     68 void AsanHeapUnderflow() {
     69   scoped_ptr<int[]> array(new int[kArraySize]);
     70   // Declares the dummy value as volatile to make sure it doesn't get optimized
     71   // away.
     72   int volatile dummy = 0;
     73   // We need to store the underflow address in a temporary variable as trying to
     74   // access array[-1] will trigger a warning C4245: "conversion from 'int' to
     75   // 'size_t', signed/unsigned mismatch".
     76   int* underflow_address = &array[0] - 1;
     77   dummy = *underflow_address;
     78   base::debug::Alias(const_cast<int*>(&dummy));
     79 }
     80 
     81 void AsanHeapUseAfterFree() {
     82   scoped_ptr<int[]> array(new int[kArraySize]);
     83   // Declares the dummy value as volatile to make sure it doesn't get optimized
     84   // away.
     85   int volatile dummy = 0;
     86   int* dangling = array.get();
     87   array.reset();
     88   dummy = dangling[kArraySize / 2];
     89   base::debug::Alias(const_cast<int*>(&dummy));
     90 }
     91 
     92 #endif  // ADDRESS_SANITIZER || SYZYASAN
     93 
     94 #if defined(SYZYASAN) && defined(COMPILER_MSVC)
     95 void AsanCorruptHeapBlock() {
     96   CorruptMemoryBlock(false);
     97 }
     98 
     99 void AsanCorruptHeap() {
    100   CorruptMemoryBlock(true);
    101 }
    102 #endif  // SYZYASAN && COMPILER_MSVC
    103 
    104 }  // namespace debug
    105 }  // namespace base
    106