mirror of
https://github.com/cuberite/libdeflate.git
synced 2025-09-10 04:41:45 -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;
|
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
|
* Return the number of timer ticks that have elapsed since some unspecified
|
||||||
* point fixed at the start of program execution
|
* 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__)
|
#define ASSERT(expr) if (!(expr)) assertion_failed(#expr, __FILE__, __LINE__)
|
||||||
|
|
||||||
extern void *xmalloc(size_t size);
|
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(void);
|
||||||
extern u64 timer_ticks_to_ms(u64 ticks);
|
extern u64 timer_ticks_to_ms(u64 ticks);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user