#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "base/debug/invalid_access_win.h"
#include <windows.h>
#include <intrin.h>
#include <stdlib.h>
#include "base/check.h"
#include "base/notreached.h"
#include "build/build_config.h"
namespace base {
namespace debug {
namespace win {
namespace {
#if defined(ARCH_CPU_X86_FAMILY)
static constexpr int kNopInstructionSize = 1;
#elif defined(ARCH_CPU_ARM64)
static constexpr int kNopInstructionSize = 4;
#else
#error "Unsupported architecture"
#endif
__attribute__((naked)) int nop_sled() {
asm("nop\n"
"nop\n"
"ret\n");
}
using FuncType = decltype(&nop_sled);
void IndirectCall(FuncType* func) {
(*func)();
}
}
void TerminateWithHeapCorruption() {
__try {
HANDLE heap = ::HeapCreate(0, 0, 0);
CHECK(heap);
CHECK(HeapSetInformation(heap, HeapEnableTerminationOnCorruption, nullptr,
0));
void* addr = ::HeapAlloc(heap, 0, 0x1000);
CHECK(addr);
char* addr_mutable = reinterpret_cast<char*>(addr);
memset(addr_mutable - sizeof(addr), 0xCC, sizeof(addr));
HeapFree(heap, 0, addr);
HeapDestroy(heap);
} __except (EXCEPTION_EXECUTE_HANDLER) {
NOTREACHED();
}
abort();
}
void TerminateWithControlFlowViolation() {
FuncType func = reinterpret_cast<FuncType>(
(reinterpret_cast<uintptr_t>(nop_sled)) + kNopInstructionSize);
__try {
IndirectCall(&func);
} __except (EXCEPTION_EXECUTE_HANDLER) {
NOTREACHED();
}
abort();
}
}
}
}