1*635a8641SAndroid Build Coastguard Worker // Copyright 2014 The Chromium Authors. All rights reserved. 2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file. 4*635a8641SAndroid Build Coastguard Worker 5*635a8641SAndroid Build Coastguard Worker #include "base/debug/asan_invalid_access.h" 6*635a8641SAndroid Build Coastguard Worker 7*635a8641SAndroid Build Coastguard Worker #include <stddef.h> 8*635a8641SAndroid Build Coastguard Worker 9*635a8641SAndroid Build Coastguard Worker #include <memory> 10*635a8641SAndroid Build Coastguard Worker 11*635a8641SAndroid Build Coastguard Worker #include "base/debug/alias.h" 12*635a8641SAndroid Build Coastguard Worker #include "base/logging.h" 13*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h" 14*635a8641SAndroid Build Coastguard Worker 15*635a8641SAndroid Build Coastguard Worker #if defined(OS_WIN) 16*635a8641SAndroid Build Coastguard Worker #include <windows.h> 17*635a8641SAndroid Build Coastguard Worker #endif 18*635a8641SAndroid Build Coastguard Worker 19*635a8641SAndroid Build Coastguard Worker namespace base { 20*635a8641SAndroid Build Coastguard Worker namespace debug { 21*635a8641SAndroid Build Coastguard Worker 22*635a8641SAndroid Build Coastguard Worker namespace { 23*635a8641SAndroid Build Coastguard Worker 24*635a8641SAndroid Build Coastguard Worker #if defined(OS_WIN) && defined(ADDRESS_SANITIZER) 25*635a8641SAndroid Build Coastguard Worker // Corrupt a memory block and make sure that the corruption gets detected either 26*635a8641SAndroid Build Coastguard Worker // when we free it or when another crash happens (if |induce_crash| is set to 27*635a8641SAndroid Build Coastguard Worker // true). CorruptMemoryBlock(bool induce_crash)28*635a8641SAndroid Build Coastguard WorkerNOINLINE void CorruptMemoryBlock(bool induce_crash) { 29*635a8641SAndroid Build Coastguard Worker // NOTE(sebmarchand): We intentionally corrupt a memory block here in order to 30*635a8641SAndroid Build Coastguard Worker // trigger an Address Sanitizer (ASAN) error report. 31*635a8641SAndroid Build Coastguard Worker static const int kArraySize = 5; 32*635a8641SAndroid Build Coastguard Worker LONG* array = new LONG[kArraySize]; 33*635a8641SAndroid Build Coastguard Worker 34*635a8641SAndroid Build Coastguard Worker // Explicitly call out to a kernel32 function to perform the memory access. 35*635a8641SAndroid Build Coastguard Worker // This way the underflow won't be detected but the corruption will (as the 36*635a8641SAndroid Build Coastguard Worker // allocator will still be hooked). 37*635a8641SAndroid Build Coastguard Worker auto InterlockedIncrementFn = 38*635a8641SAndroid Build Coastguard Worker reinterpret_cast<LONG (*)(LONG volatile * addend)>( 39*635a8641SAndroid Build Coastguard Worker GetProcAddress(GetModuleHandle(L"kernel32"), "InterlockedIncrement")); 40*635a8641SAndroid Build Coastguard Worker CHECK(InterlockedIncrementFn); 41*635a8641SAndroid Build Coastguard Worker 42*635a8641SAndroid Build Coastguard Worker LONG volatile dummy = InterlockedIncrementFn(array - 1); 43*635a8641SAndroid Build Coastguard Worker base::debug::Alias(const_cast<LONG*>(&dummy)); 44*635a8641SAndroid Build Coastguard Worker 45*635a8641SAndroid Build Coastguard Worker if (induce_crash) 46*635a8641SAndroid Build Coastguard Worker CHECK(false); 47*635a8641SAndroid Build Coastguard Worker delete[] array; 48*635a8641SAndroid Build Coastguard Worker } 49*635a8641SAndroid Build Coastguard Worker #endif // OS_WIN && ADDRESS_SANITIZER 50*635a8641SAndroid Build Coastguard Worker 51*635a8641SAndroid Build Coastguard Worker } // namespace 52*635a8641SAndroid Build Coastguard Worker 53*635a8641SAndroid Build Coastguard Worker #if defined(ADDRESS_SANITIZER) 54*635a8641SAndroid Build Coastguard Worker // NOTE(sebmarchand): We intentionally perform some invalid heap access here in 55*635a8641SAndroid Build Coastguard Worker // order to trigger an AddressSanitizer (ASan) error report. 56*635a8641SAndroid Build Coastguard Worker 57*635a8641SAndroid Build Coastguard Worker static const size_t kArraySize = 5; 58*635a8641SAndroid Build Coastguard Worker AsanHeapOverflow()59*635a8641SAndroid Build Coastguard Workervoid AsanHeapOverflow() { 60*635a8641SAndroid Build Coastguard Worker // Declares the array as volatile to make sure it doesn't get optimized away. 61*635a8641SAndroid Build Coastguard Worker std::unique_ptr<volatile int[]> array( 62*635a8641SAndroid Build Coastguard Worker const_cast<volatile int*>(new int[kArraySize])); 63*635a8641SAndroid Build Coastguard Worker int dummy = array[kArraySize]; 64*635a8641SAndroid Build Coastguard Worker base::debug::Alias(&dummy); 65*635a8641SAndroid Build Coastguard Worker } 66*635a8641SAndroid Build Coastguard Worker AsanHeapUnderflow()67*635a8641SAndroid Build Coastguard Workervoid AsanHeapUnderflow() { 68*635a8641SAndroid Build Coastguard Worker // Declares the array as volatile to make sure it doesn't get optimized away. 69*635a8641SAndroid Build Coastguard Worker std::unique_ptr<volatile int[]> array( 70*635a8641SAndroid Build Coastguard Worker const_cast<volatile int*>(new int[kArraySize])); 71*635a8641SAndroid Build Coastguard Worker // We need to store the underflow address in a temporary variable as trying to 72*635a8641SAndroid Build Coastguard Worker // access array[-1] will trigger a warning C4245: "conversion from 'int' to 73*635a8641SAndroid Build Coastguard Worker // 'size_t', signed/unsigned mismatch". 74*635a8641SAndroid Build Coastguard Worker volatile int* underflow_address = &array[0] - 1; 75*635a8641SAndroid Build Coastguard Worker int dummy = *underflow_address; 76*635a8641SAndroid Build Coastguard Worker base::debug::Alias(&dummy); 77*635a8641SAndroid Build Coastguard Worker } 78*635a8641SAndroid Build Coastguard Worker AsanHeapUseAfterFree()79*635a8641SAndroid Build Coastguard Workervoid AsanHeapUseAfterFree() { 80*635a8641SAndroid Build Coastguard Worker // Declares the array as volatile to make sure it doesn't get optimized away. 81*635a8641SAndroid Build Coastguard Worker std::unique_ptr<volatile int[]> array( 82*635a8641SAndroid Build Coastguard Worker const_cast<volatile int*>(new int[kArraySize])); 83*635a8641SAndroid Build Coastguard Worker volatile int* dangling = array.get(); 84*635a8641SAndroid Build Coastguard Worker array.reset(); 85*635a8641SAndroid Build Coastguard Worker int dummy = dangling[kArraySize / 2]; 86*635a8641SAndroid Build Coastguard Worker base::debug::Alias(&dummy); 87*635a8641SAndroid Build Coastguard Worker } 88*635a8641SAndroid Build Coastguard Worker 89*635a8641SAndroid Build Coastguard Worker #if defined(OS_WIN) AsanCorruptHeapBlock()90*635a8641SAndroid Build Coastguard Workervoid AsanCorruptHeapBlock() { 91*635a8641SAndroid Build Coastguard Worker CorruptMemoryBlock(false); 92*635a8641SAndroid Build Coastguard Worker } 93*635a8641SAndroid Build Coastguard Worker AsanCorruptHeap()94*635a8641SAndroid Build Coastguard Workervoid AsanCorruptHeap() { 95*635a8641SAndroid Build Coastguard Worker CorruptMemoryBlock(true); 96*635a8641SAndroid Build Coastguard Worker } 97*635a8641SAndroid Build Coastguard Worker #endif // OS_WIN 98*635a8641SAndroid Build Coastguard Worker #endif // ADDRESS_SANITIZER 99*635a8641SAndroid Build Coastguard Worker 100*635a8641SAndroid Build Coastguard Worker } // namespace debug 101*635a8641SAndroid Build Coastguard Worker } // namespace base 102