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