summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArseny Kapoulkine <arseny.kapoulkine@gmail.com>2015-03-01 20:57:22 -0800
committerArseny Kapoulkine <arseny.kapoulkine@gmail.com>2015-03-01 20:57:22 -0800
commitee4e2b866993f264349ea294d0114a12d3696aa7 (patch)
tree966ebe336eefa0620b8f0f182d26272ceeb62660
parent35a63cb1e63d3487cf68f73e963b6f1e58cf45da (diff)
tests: Implement page heap for OSX/Linux
Align allocations to right end of page boundary to catch buffer overruns, instead of unmapping on deallocations mark the page as no-access to guarantee a page fault on use-after-free.
-rw-r--r--tests/allocator.cpp44
1 files changed, 44 insertions, 0 deletions
diff --git a/tests/allocator.cpp b/tests/allocator.cpp
index 094d5e5..74bbf10 100644
--- a/tests/allocator.cpp
+++ b/tests/allocator.cpp
@@ -66,6 +66,50 @@ namespace
VirtualProtect(rptr, aligned_size + PAGE_SIZE, PAGE_NOACCESS, &old_flags);
}
}
+#elif defined(__APPLE__) || defined(__linux__)
+# include <sys/mman.h>
+
+namespace
+{
+ const size_t PAGE_SIZE = 4096;
+
+ size_t align_to_page(size_t value)
+ {
+ return (value + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
+ }
+
+ void* allocate_page_aligned(size_t size)
+ {
+ return mmap(0, size + PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+ }
+
+ void* allocate(size_t size)
+ {
+ size_t aligned_size = align_to_page(size);
+
+ void* ptr = allocate_page_aligned(aligned_size + PAGE_SIZE);
+ if (!ptr) return 0;
+
+ char* end = static_cast<char*>(ptr) + aligned_size;
+
+ int res = mprotect(end, PAGE_SIZE, PROT_NONE);
+ assert(res == 0);
+ (void)!res;
+
+ return end - size;
+ }
+
+ void deallocate(void* ptr, size_t size)
+ {
+ size_t aligned_size = align_to_page(size);
+
+ void* rptr = static_cast<char*>(ptr) + size - aligned_size;
+
+ int res = mprotect(rptr, aligned_size + PAGE_SIZE, PROT_NONE);
+ assert(res == 0);
+ (void)!res;
+ }
+}
#else
# include <stdlib.h>