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