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)
     20 // Corrupt a memory block and make sure that the corruption gets detected either
     21 // when we free it or when another crash happens (if |induce_crash| is set to
     22 // true).
     23 NOINLINE void CorruptMemoryBlock(bool induce_crash) {
     24   // NOTE(sebmarchand): We intentionally corrupt a memory block here in order to
     25   //     trigger an Address Sanitizer (ASAN) error report.
     26   static const int kArraySize = 5;
     27   int* array = new int[kArraySize];
     28   // Encapsulate the invalid memory access into a try-catch statement to prevent
     29   // this function from being instrumented. This way the underflow won't be
     30   // detected but the corruption will (as the allocator will still be hooked).
     31   try {
     32     // Declares the dummy value as volatile to make sure it doesn't get
     33     // optimized away.
     34     int volatile dummy = array[-1]--;
     35     base::debug::Alias(const_cast<int*>(&dummy));
     36   } catch (...) {
     37   }
     38   if (induce_crash)
     39     CHECK(false);
     40   delete[] array;
     41 }
     42 #endif
     43 
     44 }  // namespace
     45 
     46 #if defined(ADDRESS_SANITIZER) || defined(SYZYASAN)
     47 // NOTE(sebmarchand): We intentionally perform some invalid heap access here in
     48 //     order to trigger an AddressSanitizer (ASan) error report.
     49 
     50 static const int kArraySize = 5;
     51 
     52 void AsanHeapOverflow() {
     53   scoped_ptr<int[]> array(new int[kArraySize]);
     54   // Declares the dummy value as volatile to make sure it doesn't get optimized
     55   // away.
     56   int volatile dummy = 0;
     57   dummy = array[kArraySize];
     58   base::debug::Alias(const_cast<int*>(&dummy));
     59 }
     60 
     61 void AsanHeapUnderflow() {
     62   scoped_ptr<int[]> array(new int[kArraySize]);
     63   // Declares the dummy value as volatile to make sure it doesn't get optimized
     64   // away.
     65   int volatile dummy = 0;
     66   dummy = array[-1];
     67   base::debug::Alias(const_cast<int*>(&dummy));
     68 }
     69 
     70 void AsanHeapUseAfterFree() {
     71   scoped_ptr<int[]> array(new int[kArraySize]);
     72   // Declares the dummy value as volatile to make sure it doesn't get optimized
     73   // away.
     74   int volatile dummy = 0;
     75   int* dangling = array.get();
     76   array.reset();
     77   dummy = dangling[kArraySize / 2];
     78   base::debug::Alias(const_cast<int*>(&dummy));
     79 }
     80 
     81 #endif  // ADDRESS_SANITIZER || SYZYASAN
     82 
     83 #if defined(SYZYASAN)
     84 void AsanCorruptHeapBlock() {
     85   CorruptMemoryBlock(false);
     86 }
     87 
     88 void AsanCorruptHeap() {
     89   CorruptMemoryBlock(true);
     90 }
     91 #endif  // SYZYASAN
     92 
     93 }  // namespace debug
     94 }  // namespace base
     95