diff options
| author | Arseny Kapoulkine <arseny.kapoulkine@gmail.com> | 2015-03-01 20:57:22 -0800 | 
|---|---|---|
| committer | Arseny Kapoulkine <arseny.kapoulkine@gmail.com> | 2015-03-01 20:57:22 -0800 | 
| commit | ee4e2b866993f264349ea294d0114a12d3696aa7 (patch) | |
| tree | 966ebe336eefa0620b8f0f182d26272ceeb62660 /tests | |
| parent | 35a63cb1e63d3487cf68f73e963b6f1e58cf45da (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.
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/allocator.cpp | 44 | 
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> | 
