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