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