allocations/lib.rs
1use libc::size_t;
2use std::ffi::c_void;
3
4#[cfg(windows)]
5use windows::Win32::System::{Memory, SystemInformation};
6
7#[cfg(unix)]
8use libc::{mmap, munmap, MAP_ANON, MAP_PRIVATE, PROT_READ, PROT_WRITE};
9#[cfg(unix)]
10use std::ptr::null_mut;
11
12#[cfg(unix)]
13pub fn allocate(size: size_t) -> *mut c_void {
14 unsafe {
15 // With the first argument being zero the kernel picks a page-aligned address to start
16 // Then the size(for now is 1024). This is Read/Write Memory so we need those flags.
17 // MAP_PRIVATE makes a copy-on-write mapping, where updates to the mapping are not visible to other processes.
18 // MAP_ANON means it is not backed by a file, so fd is ignored, however some implementations want it to be -1 so it's -1
19 // Offset is 0.
20 mmap(
21 null_mut(),
22 size,
23 PROT_READ | PROT_WRITE,
24 MAP_PRIVATE | MAP_ANON,
25 -1,
26 0,
27 )
28 }
29}
30/// # Safety
31/// ptr should be a valid pointer into a program allocated structure. size+ptr should never be larger than the allocation bound.
32/// Furthermore ptr should no longer be stored as it is a dangling pointer after deallocation
33#[cfg(unix)]
34pub unsafe fn deallocate(ptr: *mut c_void, size: size_t) -> i32 {
35 munmap(ptr, size)
36}
37
38#[cfg(windows)]
39pub fn allocate(size: usize) -> *mut c_void {
40 unsafe {
41 let protection = Memory::PAGE_READWRITE;
42 let flags = Memory::MEM_RESERVE | Memory::MEM_COMMIT;
43 // https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc
44 let address = Memory::VirtualAlloc(None, size, flags, protection);
45 // In an allocator we shall return zero if the allocation failed. Panicing during an allocation is undefined behavior
46 address
47 }
48}
49
50/// # Safety
51/// ptr should be a valid pointer into a program allocated structure. size+ptr should never be larger than the allocation bound.
52/// Furthermore, ptr should no longer be stored as it is a dangling pointer after deallocation and using it is Use-After-Free
53#[cfg(windows)]
54pub unsafe fn deallocate(ptr: *mut c_void, size: size_t) -> i32 {
55 // https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualfree
56 // We can apparently SKIP the length which is really confusing...
57 let length = 0;
58 let flags = Memory::MEM_RELEASE;
59 match Memory::VirtualFree(ptr, length, flags) {
60 Ok(()) => 0,
61 _ => -1,
62 }
63}