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