xref: /aosp_15_r20/external/cronet/base/debug/invalid_access_win.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2018 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/invalid_access_win.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <windows.h>
8*6777b538SAndroid Build Coastguard Worker 
9*6777b538SAndroid Build Coastguard Worker #include <intrin.h>
10*6777b538SAndroid Build Coastguard Worker #include <stdlib.h>
11*6777b538SAndroid Build Coastguard Worker 
12*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
13*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
14*6777b538SAndroid Build Coastguard Worker 
15*6777b538SAndroid Build Coastguard Worker namespace base {
16*6777b538SAndroid Build Coastguard Worker namespace debug {
17*6777b538SAndroid Build Coastguard Worker namespace win {
18*6777b538SAndroid Build Coastguard Worker 
19*6777b538SAndroid Build Coastguard Worker namespace {
20*6777b538SAndroid Build Coastguard Worker 
21*6777b538SAndroid Build Coastguard Worker #if defined(ARCH_CPU_X86_FAMILY)
22*6777b538SAndroid Build Coastguard Worker // On x86/x64 systems, nop instructions are generally 1 byte.
23*6777b538SAndroid Build Coastguard Worker static constexpr int kNopInstructionSize = 1;
24*6777b538SAndroid Build Coastguard Worker #elif defined(ARCH_CPU_ARM64)
25*6777b538SAndroid Build Coastguard Worker // On Arm systems, all instructions are 4 bytes, fixed size.
26*6777b538SAndroid Build Coastguard Worker static constexpr int kNopInstructionSize = 4;
27*6777b538SAndroid Build Coastguard Worker #else
28*6777b538SAndroid Build Coastguard Worker #error "Unsupported architecture"
29*6777b538SAndroid Build Coastguard Worker #endif
30*6777b538SAndroid Build Coastguard Worker 
31*6777b538SAndroid Build Coastguard Worker // Function that can be jumped midway into safely.
nop_sled()32*6777b538SAndroid Build Coastguard Worker __attribute__((naked)) int nop_sled() {
33*6777b538SAndroid Build Coastguard Worker   asm("nop\n"
34*6777b538SAndroid Build Coastguard Worker       "nop\n"
35*6777b538SAndroid Build Coastguard Worker       "ret\n");
36*6777b538SAndroid Build Coastguard Worker }
37*6777b538SAndroid Build Coastguard Worker 
38*6777b538SAndroid Build Coastguard Worker using FuncType = decltype(&nop_sled);
39*6777b538SAndroid Build Coastguard Worker 
IndirectCall(FuncType * func)40*6777b538SAndroid Build Coastguard Worker void IndirectCall(FuncType* func) {
41*6777b538SAndroid Build Coastguard Worker   // This code always generates CFG guards.
42*6777b538SAndroid Build Coastguard Worker   (*func)();
43*6777b538SAndroid Build Coastguard Worker }
44*6777b538SAndroid Build Coastguard Worker 
45*6777b538SAndroid Build Coastguard Worker }  // namespace
46*6777b538SAndroid Build Coastguard Worker 
TerminateWithHeapCorruption()47*6777b538SAndroid Build Coastguard Worker void TerminateWithHeapCorruption() {
48*6777b538SAndroid Build Coastguard Worker   __try {
49*6777b538SAndroid Build Coastguard Worker     HANDLE heap = ::HeapCreate(0, 0, 0);
50*6777b538SAndroid Build Coastguard Worker     CHECK(heap);
51*6777b538SAndroid Build Coastguard Worker     CHECK(HeapSetInformation(heap, HeapEnableTerminationOnCorruption, nullptr,
52*6777b538SAndroid Build Coastguard Worker                              0));
53*6777b538SAndroid Build Coastguard Worker     void* addr = ::HeapAlloc(heap, 0, 0x1000);
54*6777b538SAndroid Build Coastguard Worker     CHECK(addr);
55*6777b538SAndroid Build Coastguard Worker     // Corrupt heap header.
56*6777b538SAndroid Build Coastguard Worker     char* addr_mutable = reinterpret_cast<char*>(addr);
57*6777b538SAndroid Build Coastguard Worker     memset(addr_mutable - sizeof(addr), 0xCC, sizeof(addr));
58*6777b538SAndroid Build Coastguard Worker 
59*6777b538SAndroid Build Coastguard Worker     HeapFree(heap, 0, addr);
60*6777b538SAndroid Build Coastguard Worker     HeapDestroy(heap);
61*6777b538SAndroid Build Coastguard Worker   } __except (EXCEPTION_EXECUTE_HANDLER) {
62*6777b538SAndroid Build Coastguard Worker     // Heap corruption exception should never be caught.
63*6777b538SAndroid Build Coastguard Worker     CHECK(false);
64*6777b538SAndroid Build Coastguard Worker   }
65*6777b538SAndroid Build Coastguard Worker   // Should never reach here.
66*6777b538SAndroid Build Coastguard Worker   abort();
67*6777b538SAndroid Build Coastguard Worker }
68*6777b538SAndroid Build Coastguard Worker 
TerminateWithControlFlowViolation()69*6777b538SAndroid Build Coastguard Worker void TerminateWithControlFlowViolation() {
70*6777b538SAndroid Build Coastguard Worker   // Call into the middle of the NOP sled.
71*6777b538SAndroid Build Coastguard Worker   FuncType func = reinterpret_cast<FuncType>(
72*6777b538SAndroid Build Coastguard Worker       (reinterpret_cast<uintptr_t>(nop_sled)) + kNopInstructionSize);
73*6777b538SAndroid Build Coastguard Worker   __try {
74*6777b538SAndroid Build Coastguard Worker     // Generates a STATUS_STACK_BUFFER_OVERRUN exception if CFG triggers.
75*6777b538SAndroid Build Coastguard Worker     IndirectCall(&func);
76*6777b538SAndroid Build Coastguard Worker   } __except (EXCEPTION_EXECUTE_HANDLER) {
77*6777b538SAndroid Build Coastguard Worker     // CFG fast fail should never be caught.
78*6777b538SAndroid Build Coastguard Worker     CHECK(false);
79*6777b538SAndroid Build Coastguard Worker   }
80*6777b538SAndroid Build Coastguard Worker   // Should only reach here if CFG is disabled.
81*6777b538SAndroid Build Coastguard Worker   abort();
82*6777b538SAndroid Build Coastguard Worker }
83*6777b538SAndroid Build Coastguard Worker 
84*6777b538SAndroid Build Coastguard Worker }  // namespace win
85*6777b538SAndroid Build Coastguard Worker }  // namespace debug
86*6777b538SAndroid Build Coastguard Worker }  // namespace base
87