mirror of
https://github.com/cuberite/libdeflate.git
synced 2025-09-07 19:26:29 -04:00
prog_util: add guarded buffer allocator
This commit is contained in:
parent
57cab078f1
commit
a5a4822e2a
@ -115,6 +115,97 @@ xmalloc(size_t size)
|
||||
return p;
|
||||
}
|
||||
|
||||
static size_t
|
||||
get_page_size(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
SYSTEM_INFO info;
|
||||
|
||||
GetSystemInfo(&info);
|
||||
return info.dwPageSize;
|
||||
#else
|
||||
return sysconf(_SC_PAGESIZE);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Allocate a buffer with guard pages */
|
||||
int
|
||||
alloc_guarded_buffer(size_t size, u8 **start_ret, u8 **end_ret)
|
||||
{
|
||||
const size_t pagesize = get_page_size();
|
||||
const size_t nr_pages = (size + pagesize - 1) / pagesize;
|
||||
u8 *base_addr;
|
||||
u8 *start, *end;
|
||||
#ifdef _WIN32
|
||||
DWORD oldProtect;
|
||||
#else
|
||||
int fd;
|
||||
#endif
|
||||
|
||||
*start_ret = NULL;
|
||||
*end_ret = NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Allocate buffer and guard pages with no access. */
|
||||
base_addr = VirtualAlloc(NULL, (nr_pages + 2) * pagesize,
|
||||
MEM_COMMIT | MEM_RESERVE, PAGE_NOACCESS);
|
||||
if (!base_addr) {
|
||||
msg("Unable to allocate memory (VirtualAlloc): Windows error %u",
|
||||
(unsigned int)GetLastError());
|
||||
return -1;
|
||||
}
|
||||
start = base_addr + pagesize;
|
||||
end = start + (nr_pages * pagesize);
|
||||
|
||||
/* Grant read+write access to just the buffer. */
|
||||
if (!VirtualProtect(start, end - start, PAGE_READWRITE, &oldProtect)) {
|
||||
msg("Unable to protect memory (VirtualProtect): Windows error %u",
|
||||
(unsigned int)GetLastError());
|
||||
VirtualFree(base_addr, 0, MEM_RELEASE);
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* Allocate buffer and guard pages.
|
||||
* For portability, use /dev/zero instead of MAP_ANONYMOUS.
|
||||
*/
|
||||
fd = open("/dev/zero", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
msg_errno("Unable to open /dev/zero");
|
||||
return -1;
|
||||
}
|
||||
base_addr = mmap(NULL, (nr_pages + 2) * pagesize,
|
||||
PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
|
||||
close(fd);
|
||||
if (base_addr == (u8 *)MAP_FAILED) {
|
||||
msg_errno("Unable to allocate memory (unable to mmap /dev/zero)");
|
||||
return -1;
|
||||
}
|
||||
start = base_addr + pagesize;
|
||||
end = start + (nr_pages * pagesize);
|
||||
|
||||
/* Unmap the guard pages. */
|
||||
munmap(base_addr, pagesize);
|
||||
munmap(end, pagesize);
|
||||
#endif
|
||||
*start_ret = start;
|
||||
*end_ret = end;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Free a buffer that was allocated by alloc_guarded_buffer() */
|
||||
void
|
||||
free_guarded_buffer(u8 *start, u8 *end)
|
||||
{
|
||||
if (!start)
|
||||
return;
|
||||
#ifdef _WIN32
|
||||
VirtualFree(start - get_page_size(), 0, MEM_RELEASE);
|
||||
#else
|
||||
munmap(start, end - start);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the number of timer ticks that have elapsed since some unspecified
|
||||
* point fixed at the start of program execution
|
||||
|
@ -127,6 +127,8 @@ assertion_failed(const char *expr, const char *file, int line);
|
||||
#define ASSERT(expr) if (!(expr)) assertion_failed(#expr, __FILE__, __LINE__)
|
||||
|
||||
extern void *xmalloc(size_t size);
|
||||
extern int alloc_guarded_buffer(size_t size, u8 **start_ret, u8 **end_ret);
|
||||
extern void free_guarded_buffer(u8 *start, u8 *end);
|
||||
|
||||
extern u64 timer_ticks(void);
|
||||
extern u64 timer_ticks_to_ms(u64 ticks);
|
||||
|
Loading…
x
Reference in New Issue
Block a user