Add some function to induce ASan crashes.

This will allows to induce ASan crashes in the browser and in the renderer processes, this is really useful when trying to debug an ASan crash (to make sure that the build is really instrumented).

This code add the following crash urls to chrome:

chrome://crash/browser-heap-overflow
chrome://crash/browser-heap-underflow
chrome://crash/browser-use-after-free
chrome://crash/browser-corrupt-heap-block
chrome://crash/browser-corrupt-heap

Those URLs induce a crash in the browser process, while those:

chrome://crash/heap-overflow
chrome://crash/heap-underflow
chrome://crash/use-after-free
chrome://crash/corrupt-heap-block
chrome://crash/corrupt-heap

induce a crash in the renderer process.

We need this because as these process use a different DLL (chrome.dll vs
chrome_child.dll) one of them could be ASan-instrumented while the other one
isn't... So the current code in renderer/ is useless for the browser-only
instrumented builds...


BUG=

Review URL: https://codereview.chromium.org/306753003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@277201 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/base/debug/asan_invalid_access.cc b/base/debug/asan_invalid_access.cc
new file mode 100644
index 0000000..ff7788a3
--- /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