Skip to content

Instantly share code, notes, and snippets.

@xtuc
Last active January 25, 2019 16:05
Show Gist options
  • Save xtuc/080831414022dc56f78fbfa94d18f1a2 to your computer and use it in GitHub Desktop.
Save xtuc/080831414022dc56f78fbfa94d18f1a2 to your computer and use it in GitHub Desktop.
Test memory bound checks vs guard pages
#include <iostream>
#include <sys/mman.h>
#include <chrono>
#define CHECK(b) \
do { \
if (!(b)) { \
fprintf(stderr, #b": incorrect assertion.\n"); \
abort(); \
} \
} while(0) \
constexpr int OS_PAGE_SIZE = 4 * 1024; // 4kb
constexpr int GUARD_SIZE = OS_PAGE_SIZE;
constexpr int USER_MEM_SIZE = 65536 * OS_PAGE_SIZE; // 256Mb
#define RUN_BENCH \
for (int ii = 0; ii < 10; ii++) \
for (int i = 0; i < USER_MEM_SIZE; i++) \
#define PTR(base) reinterpret_cast<uint8_t*>(base)
#define STORE(base, value) *PTR(base) = value
#define LOAD(base) *PTR(base)
void* alloc(int size)
{
auto mem = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
CHECK(mem != MAP_FAILED); // allocate memory
return mem;
}
void test_with_guards()
{
void* mem = alloc(USER_MEM_SIZE + (GUARD_SIZE * 2));
uintptr_t mem_start = reinterpret_cast<uintptr_t>(mem);
CHECK(mprotect((void*) mem_start, GUARD_SIZE, PROT_NONE) == 0); // protected start guard
CHECK(mprotect((void*) (mem_start + GUARD_SIZE + USER_MEM_SIZE), GUARD_SIZE, PROT_NONE) == 0); // protected end guard
auto start_time = std::chrono::high_resolution_clock::now();
RUN_BENCH {
auto value = i % 255;
auto ptr = mem_start + i + GUARD_SIZE;
STORE(ptr, value);
CHECK(LOAD(ptr) == value);
}
auto end_time = std::chrono::high_resolution_clock::now();
auto time = end_time - start_time;
std::cout << "test_with_guards:\t" << time / std::chrono::milliseconds(1) << " ms to run.\n";
}
void test_with_checks()
{
void* mem = alloc(USER_MEM_SIZE);
uintptr_t mem_start = reinterpret_cast<uintptr_t>(mem);
auto start_time = std::chrono::high_resolution_clock::now();
RUN_BENCH {
auto value = i % 255;
auto ptr = mem_start + i;
CHECK(ptr >= mem_start && ptr < mem_start + USER_MEM_SIZE);
STORE(ptr, value);
CHECK(ptr >= mem_start && ptr < mem_start + USER_MEM_SIZE);
CHECK(LOAD(ptr) == value);
}
auto end_time = std::chrono::high_resolution_clock::now();
auto time = end_time - start_time;
std::cout << "test_with_checks:\t" << time / std::chrono::milliseconds(1) << " ms to run.\n";
}
int main()
{
test_with_guards();
test_with_checks();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment