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