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}