Index: base/debug/asan_invalid_access.cc |
diff --git a/base/debug/asan_invalid_access.cc b/base/debug/asan_invalid_access.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ff7788a39cc6eef35151cc8bde487992fd453630 |
--- /dev/null |
+++ b/base/debug/asan_invalid_access.cc |
@@ -0,0 +1,94 @@ |
+// 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) |
+// 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; |
+} |
+#endif |
+ |
+} // 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 int 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; |
+ dummy = array[-1]; |
+ 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) |
+void AsanCorruptHeapBlock() { |
+ CorruptMemoryBlock(false); |
+} |
+ |
+void AsanCorruptHeap() { |
+ CorruptMemoryBlock(true); |
+} |
+#endif // SYZYASAN |
+ |
+} // namespace debug |
+} // namespace base |