#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "base/debug/asan_invalid_access.h"
#include <stddef.h>
#include <memory>
#include "base/check.h"
#include "base/debug/alias.h"
#include "build/build_config.h"
#if BUILDFLAG(IS_WIN)
#include <windows.h>
#endif
namespace base {
namespace debug {
namespace {
#if BUILDFLAG(IS_WIN) && defined(ADDRESS_SANITIZER)
NOINLINE void CorruptMemoryBlock(bool induce_crash) {
static const int kArraySize = 5;
LONG* array = new LONG[kArraySize];
auto InterlockedIncrementFn =
reinterpret_cast<LONG (*)(LONG volatile * addend)>(
GetProcAddress(GetModuleHandle(L"kernel32"), "InterlockedIncrement"));
CHECK(InterlockedIncrementFn);
LONG volatile dummy = InterlockedIncrementFn(array - 1);
base::debug::Alias(const_cast<LONG*>(&dummy));
if (induce_crash)
CHECK(false);
delete[] array;
}
#endif
}
#if defined(ADDRESS_SANITIZER) || BUILDFLAG(IS_HWASAN)
static const size_t kArraySize = 4;
void AsanHeapOverflow() {
std::unique_ptr<volatile int[]> array(
const_cast<volatile int*>(new int[kArraySize]));
int dummy = array[kArraySize];
base::debug::Alias(&dummy);
}
void AsanHeapUnderflow() {
std::unique_ptr<volatile int[]> array(
const_cast<volatile int*>(new int[kArraySize]));
volatile int* underflow_address = &array[0] - 1;
int dummy = *underflow_address;
base::debug::Alias(&dummy);
}
void AsanHeapUseAfterFree() {
std::unique_ptr<volatile int[]> array(
const_cast<volatile int*>(new int[kArraySize]));
volatile int* dangling = array.get();
array.reset();
int dummy = dangling[kArraySize / 2];
base::debug::Alias(&dummy);
}
#if BUILDFLAG(IS_WIN)
void AsanCorruptHeapBlock() {
CorruptMemoryBlock(false);
}
void AsanCorruptHeap() {
CorruptMemoryBlock(true);
}
#endif
#endif
}
}