|  | // Copyright 2014 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #if defined(OS_WIN) | 
|  | #include <windows.h> | 
|  | #endif | 
|  |  | 
|  | #include "base/debug/alias.h" | 
|  | #include "base/debug/asan_invalid_access.h" | 
|  | #include "base/logging.h" | 
|  | #include "base/memory/scoped_ptr.h" | 
|  |  | 
|  | namespace base { | 
|  | namespace debug { | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | #if defined(SYZYASAN) && defined(COMPILER_MSVC) | 
|  | // Disable warning C4530: "C++ exception handler used, but unwind semantics are | 
|  | // not enabled". We don't want to change the compilation flags just for this | 
|  | // test, and no exception should be triggered here, so this warning has no value | 
|  | // here. | 
|  | #pragma warning(push) | 
|  | #pragma warning(disable: 4530) | 
|  | // Corrupt a memory block and make sure that the corruption gets detected either | 
|  | // when we free it or when another crash happens (if |induce_crash| is set to | 
|  | // true). | 
|  | NOINLINE void CorruptMemoryBlock(bool induce_crash) { | 
|  | // NOTE(sebmarchand): We intentionally corrupt a memory block here in order to | 
|  | //     trigger an Address Sanitizer (ASAN) error report. | 
|  | static const int kArraySize = 5; | 
|  | int* array = new int[kArraySize]; | 
|  | // Encapsulate the invalid memory access into a try-catch statement to prevent | 
|  | // this function from being instrumented. This way the underflow won't be | 
|  | // detected but the corruption will (as the allocator will still be hooked). | 
|  | try { | 
|  | // Declares the dummy value as volatile to make sure it doesn't get | 
|  | // optimized away. | 
|  | int volatile dummy = array[-1]--; | 
|  | base::debug::Alias(const_cast<int*>(&dummy)); | 
|  | } catch (...) { | 
|  | } | 
|  | if (induce_crash) | 
|  | CHECK(false); | 
|  | delete[] array; | 
|  | } | 
|  | #pragma warning(pop) | 
|  | #endif  // SYZYASAN && COMPILER_MSVC | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | #if defined(ADDRESS_SANITIZER) || defined(SYZYASAN) | 
|  | // NOTE(sebmarchand): We intentionally perform some invalid heap access here in | 
|  | //     order to trigger an AddressSanitizer (ASan) error report. | 
|  |  | 
|  | static const size_t kArraySize = 5; | 
|  |  | 
|  | void AsanHeapOverflow() { | 
|  | scoped_ptr<int[]> array(new int[kArraySize]); | 
|  | // Declares the dummy value as volatile to make sure it doesn't get optimized | 
|  | // away. | 
|  | int volatile dummy = 0; | 
|  | dummy = array[kArraySize]; | 
|  | base::debug::Alias(const_cast<int*>(&dummy)); | 
|  | } | 
|  |  | 
|  | void AsanHeapUnderflow() { | 
|  | scoped_ptr<int[]> array(new int[kArraySize]); | 
|  | // Declares the dummy value as volatile to make sure it doesn't get optimized | 
|  | // away. | 
|  | int volatile dummy = 0; | 
|  | // We need to store the underflow address in a temporary variable as trying to | 
|  | // access array[-1] will trigger a warning C4245: "conversion from 'int' to | 
|  | // 'size_t', signed/unsigned mismatch". | 
|  | int* underflow_address = &array[0] - 1; | 
|  | dummy = *underflow_address; | 
|  | base::debug::Alias(const_cast<int*>(&dummy)); | 
|  | } | 
|  |  | 
|  | void AsanHeapUseAfterFree() { | 
|  | scoped_ptr<int[]> array(new int[kArraySize]); | 
|  | // Declares the dummy value as volatile to make sure it doesn't get optimized | 
|  | // away. | 
|  | int volatile dummy = 0; | 
|  | int* dangling = array.get(); | 
|  | array.reset(); | 
|  | dummy = dangling[kArraySize / 2]; | 
|  | base::debug::Alias(const_cast<int*>(&dummy)); | 
|  | } | 
|  |  | 
|  | #endif  // ADDRESS_SANITIZER || SYZYASAN | 
|  |  | 
|  | #if defined(SYZYASAN) && defined(COMPILER_MSVC) | 
|  | void AsanCorruptHeapBlock() { | 
|  | CorruptMemoryBlock(false); | 
|  | } | 
|  |  | 
|  | void AsanCorruptHeap() { | 
|  | CorruptMemoryBlock(true); | 
|  | } | 
|  | #endif  // SYZYASAN && COMPILER_MSVC | 
|  |  | 
|  | }  // namespace debug | 
|  | }  // namespace base |