asan_invalid_access.cc 2.7 KB

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