xref: /aosp_15_r20/external/libchrome/base/debug/asan_invalid_access.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright 2014 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker #include "base/debug/asan_invalid_access.h"
6*635a8641SAndroid Build Coastguard Worker 
7*635a8641SAndroid Build Coastguard Worker #include <stddef.h>
8*635a8641SAndroid Build Coastguard Worker 
9*635a8641SAndroid Build Coastguard Worker #include <memory>
10*635a8641SAndroid Build Coastguard Worker 
11*635a8641SAndroid Build Coastguard Worker #include "base/debug/alias.h"
12*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
13*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h"
14*635a8641SAndroid Build Coastguard Worker 
15*635a8641SAndroid Build Coastguard Worker #if defined(OS_WIN)
16*635a8641SAndroid Build Coastguard Worker #include <windows.h>
17*635a8641SAndroid Build Coastguard Worker #endif
18*635a8641SAndroid Build Coastguard Worker 
19*635a8641SAndroid Build Coastguard Worker namespace base {
20*635a8641SAndroid Build Coastguard Worker namespace debug {
21*635a8641SAndroid Build Coastguard Worker 
22*635a8641SAndroid Build Coastguard Worker namespace {
23*635a8641SAndroid Build Coastguard Worker 
24*635a8641SAndroid Build Coastguard Worker #if defined(OS_WIN) && defined(ADDRESS_SANITIZER)
25*635a8641SAndroid Build Coastguard Worker // Corrupt a memory block and make sure that the corruption gets detected either
26*635a8641SAndroid Build Coastguard Worker // when we free it or when another crash happens (if |induce_crash| is set to
27*635a8641SAndroid Build Coastguard Worker // true).
CorruptMemoryBlock(bool induce_crash)28*635a8641SAndroid Build Coastguard Worker NOINLINE void CorruptMemoryBlock(bool induce_crash) {
29*635a8641SAndroid Build Coastguard Worker   // NOTE(sebmarchand): We intentionally corrupt a memory block here in order to
30*635a8641SAndroid Build Coastguard Worker   //     trigger an Address Sanitizer (ASAN) error report.
31*635a8641SAndroid Build Coastguard Worker   static const int kArraySize = 5;
32*635a8641SAndroid Build Coastguard Worker   LONG* array = new LONG[kArraySize];
33*635a8641SAndroid Build Coastguard Worker 
34*635a8641SAndroid Build Coastguard Worker   // Explicitly call out to a kernel32 function to perform the memory access.
35*635a8641SAndroid Build Coastguard Worker   // This way the underflow won't be detected but the corruption will (as the
36*635a8641SAndroid Build Coastguard Worker   // allocator will still be hooked).
37*635a8641SAndroid Build Coastguard Worker   auto InterlockedIncrementFn =
38*635a8641SAndroid Build Coastguard Worker       reinterpret_cast<LONG (*)(LONG volatile * addend)>(
39*635a8641SAndroid Build Coastguard Worker           GetProcAddress(GetModuleHandle(L"kernel32"), "InterlockedIncrement"));
40*635a8641SAndroid Build Coastguard Worker   CHECK(InterlockedIncrementFn);
41*635a8641SAndroid Build Coastguard Worker 
42*635a8641SAndroid Build Coastguard Worker   LONG volatile dummy = InterlockedIncrementFn(array - 1);
43*635a8641SAndroid Build Coastguard Worker   base::debug::Alias(const_cast<LONG*>(&dummy));
44*635a8641SAndroid Build Coastguard Worker 
45*635a8641SAndroid Build Coastguard Worker   if (induce_crash)
46*635a8641SAndroid Build Coastguard Worker     CHECK(false);
47*635a8641SAndroid Build Coastguard Worker   delete[] array;
48*635a8641SAndroid Build Coastguard Worker }
49*635a8641SAndroid Build Coastguard Worker #endif  // OS_WIN && ADDRESS_SANITIZER
50*635a8641SAndroid Build Coastguard Worker 
51*635a8641SAndroid Build Coastguard Worker }  // namespace
52*635a8641SAndroid Build Coastguard Worker 
53*635a8641SAndroid Build Coastguard Worker #if defined(ADDRESS_SANITIZER)
54*635a8641SAndroid Build Coastguard Worker // NOTE(sebmarchand): We intentionally perform some invalid heap access here in
55*635a8641SAndroid Build Coastguard Worker //     order to trigger an AddressSanitizer (ASan) error report.
56*635a8641SAndroid Build Coastguard Worker 
57*635a8641SAndroid Build Coastguard Worker static const size_t kArraySize = 5;
58*635a8641SAndroid Build Coastguard Worker 
AsanHeapOverflow()59*635a8641SAndroid Build Coastguard Worker void AsanHeapOverflow() {
60*635a8641SAndroid Build Coastguard Worker   // Declares the array as volatile to make sure it doesn't get optimized away.
61*635a8641SAndroid Build Coastguard Worker   std::unique_ptr<volatile int[]> array(
62*635a8641SAndroid Build Coastguard Worker       const_cast<volatile int*>(new int[kArraySize]));
63*635a8641SAndroid Build Coastguard Worker   int dummy = array[kArraySize];
64*635a8641SAndroid Build Coastguard Worker   base::debug::Alias(&dummy);
65*635a8641SAndroid Build Coastguard Worker }
66*635a8641SAndroid Build Coastguard Worker 
AsanHeapUnderflow()67*635a8641SAndroid Build Coastguard Worker void AsanHeapUnderflow() {
68*635a8641SAndroid Build Coastguard Worker   // Declares the array as volatile to make sure it doesn't get optimized away.
69*635a8641SAndroid Build Coastguard Worker   std::unique_ptr<volatile int[]> array(
70*635a8641SAndroid Build Coastguard Worker       const_cast<volatile int*>(new int[kArraySize]));
71*635a8641SAndroid Build Coastguard Worker   // We need to store the underflow address in a temporary variable as trying to
72*635a8641SAndroid Build Coastguard Worker   // access array[-1] will trigger a warning C4245: "conversion from 'int' to
73*635a8641SAndroid Build Coastguard Worker   // 'size_t', signed/unsigned mismatch".
74*635a8641SAndroid Build Coastguard Worker   volatile int* underflow_address = &array[0] - 1;
75*635a8641SAndroid Build Coastguard Worker   int dummy = *underflow_address;
76*635a8641SAndroid Build Coastguard Worker   base::debug::Alias(&dummy);
77*635a8641SAndroid Build Coastguard Worker }
78*635a8641SAndroid Build Coastguard Worker 
AsanHeapUseAfterFree()79*635a8641SAndroid Build Coastguard Worker void AsanHeapUseAfterFree() {
80*635a8641SAndroid Build Coastguard Worker   // Declares the array as volatile to make sure it doesn't get optimized away.
81*635a8641SAndroid Build Coastguard Worker   std::unique_ptr<volatile int[]> array(
82*635a8641SAndroid Build Coastguard Worker       const_cast<volatile int*>(new int[kArraySize]));
83*635a8641SAndroid Build Coastguard Worker   volatile int* dangling = array.get();
84*635a8641SAndroid Build Coastguard Worker   array.reset();
85*635a8641SAndroid Build Coastguard Worker   int dummy = dangling[kArraySize / 2];
86*635a8641SAndroid Build Coastguard Worker   base::debug::Alias(&dummy);
87*635a8641SAndroid Build Coastguard Worker }
88*635a8641SAndroid Build Coastguard Worker 
89*635a8641SAndroid Build Coastguard Worker #if defined(OS_WIN)
AsanCorruptHeapBlock()90*635a8641SAndroid Build Coastguard Worker void AsanCorruptHeapBlock() {
91*635a8641SAndroid Build Coastguard Worker   CorruptMemoryBlock(false);
92*635a8641SAndroid Build Coastguard Worker }
93*635a8641SAndroid Build Coastguard Worker 
AsanCorruptHeap()94*635a8641SAndroid Build Coastguard Worker void AsanCorruptHeap() {
95*635a8641SAndroid Build Coastguard Worker   CorruptMemoryBlock(true);
96*635a8641SAndroid Build Coastguard Worker }
97*635a8641SAndroid Build Coastguard Worker #endif  // OS_WIN
98*635a8641SAndroid Build Coastguard Worker #endif  // ADDRESS_SANITIZER
99*635a8641SAndroid Build Coastguard Worker 
100*635a8641SAndroid Build Coastguard Worker }  // namespace debug
101*635a8641SAndroid Build Coastguard Worker }  // namespace base
102