alloc-stdlib-0.2.2/.cargo_vcs_info.json0000644000000001520000000000100134040ustar { "git": { "sha1": "6032b6a9b20e03737135c55a0270ccffcc1438ef" }, "path_in_vcs": "alloc-stdlib" }alloc-stdlib-0.2.2/Cargo.lock0000644000000006120000000000100113600ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "alloc-no-stdlib" version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" [[package]] name = "alloc-stdlib" version = "0.2.2" dependencies = [ "alloc-no-stdlib", ] alloc-stdlib-0.2.2/Cargo.toml0000644000000021600000000000100114030ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] name = "alloc-stdlib" version = "0.2.2" authors = ["Daniel Reiter Horn "] autobins = false description = "A dynamic allocator example that may be used with the stdlib" homepage = "https://github.com/dropbox/rust-alloc-no-stdlib" documentation = "https://raw.githubusercontent.com/dropbox/rust-alloc-no-stdlib/master/alloc-stdlib/tests/lib.rs" readme = "README.md" keywords = [ "custom", "allocator", "calloc", "safe", "nostd", ] license = "BSD-3-Clause" repository = "https://github.com/dropbox/rust-alloc-no-stdlib" [[bin]] name = "example" [dependencies.alloc-no-stdlib] version = "2.0.4" [features] unsafe = [] alloc-stdlib-0.2.2/Cargo.toml.orig000064400000000000000000000012271046102023000150670ustar 00000000000000[package] name = "alloc-stdlib" description = "A dynamic allocator example that may be used with the stdlib" version = "0.2.2" authors = ["Daniel Reiter Horn "] documentation = "https://raw.githubusercontent.com/dropbox/rust-alloc-no-stdlib/master/alloc-stdlib/tests/lib.rs" homepage = "https://github.com/dropbox/rust-alloc-no-stdlib" readme = "README.md" keywords = ["custom", "allocator", "calloc", "safe", "nostd"] license = "BSD-3-Clause" repository = "https://github.com/dropbox/rust-alloc-no-stdlib" autobins = false [[bin]] name = "example" [dependencies] "alloc-no-stdlib" = { version="2.0.4", path="../"} [features] unsafe = [] alloc-stdlib-0.2.2/README.md000064400000000000000000000151701046102023000134610ustar 00000000000000# Framework for allocating memory in #![no_std] modules. [![crates.io](http://meritbadge.herokuapp.com/alloc-no-stdlib)](https://crates.io/crates/alloc-no-stdlib) [![Build Status](https://travis-ci.org/dropbox/rust-alloc-no-stdlib.svg?branch=master)](https://travis-ci.org/dropbox/rust-alloc-no-stdlib) ## Requirements * Rust 1.6 ## Documentation Currently there is no standard way to allocate memory from within a module that is no_std. This provides a mechanism to allocate memory using the stdlib-independent memory allocation system described by rust-alloc-no-stdlib describe a memory allocation that can be satisfied entirely on the stack, by unsafely linking to calloc, or by unsafely referencing a mutable global variable. This library currently will leak memory if free_cell isn't specifically invoked on memory. However, if linked by a library that actually can depend on the stdlib then that library can simply pass in a few allocators and use the standard Box allocation and will free automatically. This library should also make it possible to entirely jail a rust application that needs dynamic allocations by preallocating a maximum limit of data upfront using calloc and using seccomp to disallow future syscalls. ## Usage There are 3 modes for allocating memory using the stdlib, each with advantages and disadvantages ### On the heap This uses the standard Box facilities to allocate memory and assumeds a default constructor for the given type ```rust let mut halloc = StandardAlloc::new(0); for _i in 1..10 { // heap test let mut x = >::alloc_cell(&mut halloc, 100000) x[0] = 4; let mut y = >::alloc_cell(&mut halloc, 100000) y[0] = 5; let mut z = >::alloc_cell(&mut halloc, 100000) z[0] = 6; assert_eq!(y[0], 5); halloc.free_cell(y); assert_eq!(x[0], 4); assert_eq!(x[9], 0); assert_eq!(z[0], 6); } ``` ### On the heap This uses the standard Box facilities to allocate memory but assuming a default user-provided value ```rust let mut halloc = HeapAlloc::::new(8); for _i in 1..10 { // heap test let mut x = halloc.alloc_cell(100000); x[0] = 4; let mut y = halloc.alloc_cell(110000); y[0] = 5; let mut z = halloc.alloc_cell(120000); z[0] = 6; assert_eq!(y[0], 5); halloc.free_cell(y); assert_eq!(x[0], 4); assert_eq!(x[9], 8); assert_eq!(z[0], 6); } ``` ### On the heap, but uninitialized This does allocate data every time it is requested, but it does not allocate the memory, so naturally it is unsafe. The caller must initialize the memory properly ```rust let mut halloc = unsafe{HeapAllocUninitialized::::new()}; { // heap test let mut x = halloc.alloc_cell(100000); x[0] = 4; let mut y = halloc.alloc_cell(110000); y[0] = 5; let mut z = halloc.alloc_cell(120000); z[0] = 6; assert_eq!(y[0], 5); halloc.free_cell(y); assert_eq!(x[0], 4); assert_eq!(x[9], 0); assert_eq!(z[0], 6); ... } ``` ### On the heap in a single pool allocation This does a single big allocation on the heap, after which no further usage of the stdlib will happen. This can be useful for a jailed application that wishes to restrict syscalls at this point ```rust use alloc_no_stdlib::HeapPrealloc; ... let mut heap_global_buffer = define_allocator_memory_pool!(4096, u8, [0; 6 * 1024 * 1024], heap); let mut ags = HeapPrealloc::::new_allocator(4096, &mut heap_global_buffer, uninitialized); { let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; let mut y = ags.alloc_cell(4); y[0] = 5; ags.free_cell(y); //y.mem[0] = 6; // <-- this is an error (use after free) } ``` ### On the heap, uninitialized This does a single big allocation on the heap, after which no further usage of the stdlib will happen. This can be useful for a jailed application that wishes to restrict syscalls at this point. This option keep does not set the memory to a valid value, so it is necessarily marked unsafe ```rust use alloc_no_stdlib::HeapPrealloc; ... let mut heap_global_buffer = unsafe{HeapPrealloc::::new_uninitialized_memory_pool(6 * 1024 * 1024)}; let mut ags = HeapPrealloc::::new_allocator(4096, &mut heap_global_buffer, uninitialized); { let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; let mut y = ags.alloc_cell(4); y[0] = 5; ags.free_cell(y); //y.mem[0] = 6; // <-- this is an error (use after free) } ``` ### With calloc This is the most efficient way to get a zero'd dynamically sized buffer without the stdlib It does invoke the C calloc function and hence must invoke unsafe code. In this version, the number of cells are fixed to the parameter specified in the struct definition (4096 in this example) ```rust extern { fn calloc(n_elem : usize, el_size : usize) -> *mut u8; fn malloc(len : usize) -> *mut u8; fn free(item : *mut u8); } declare_stack_allocator_struct!(CallocAllocatedFreelist4096, 4096, calloc); ... // the buffer is defined with 200 megs of zero'd memory from calloc let mut calloc_global_buffer = unsafe {define_allocator_memory_pool!(4096, u8, [0; 200 * 1024 * 1024], calloc)}; // and assigned to a new_allocator let mut ags = CallocAllocatedFreelist4096::::new_allocator(&mut calloc_global_buffer.data, bzero); { let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; let mut y = ags.alloc_cell(4); y[0] = 5; ags.free_cell(y); //y.mem[0] = 6; // <-- this is an error (use after free) } ``` ### With a static, mutable buffer If a single buffer of data is needed for the entire span of the application Then the simplest way to do so without a zero operation on the memory and without using the stdlib is to simply have a global allocated structure. Accessing mutable static variables requires unsafe code; however, so this code will invoke an unsafe block. Make sure to only reference global_buffer in a single place, at a single time in the code If it is used from two places or at different times, undefined behavior may result, since multiple allocators may get access to global_buffer. ```rust declare_stack_allocator_struct!(GlobalAllocatedFreelist, 16, global); define_allocator_memory_pool!(16, u8, [0; 1024 * 1024 * 100], global, global_buffer); ... // this references a global buffer let mut ags = GlobalAllocatedFreelist::::new_allocator(bzero); unsafe { bind_global_buffers_to_allocator!(ags, global_buffer, u8); } { let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; let mut y = ags.alloc_cell(4); y[0] = 5; ags.free_cell(y); //y.mem[0] = 6; // <-- this is an error (use after free) } ``` ## Contributors - Daniel Reiter Horn alloc-stdlib-0.2.2/src/bin/example.rs000064400000000000000000000074311046102023000155430ustar 00000000000000//#![feature(trace_macros)] extern crate alloc_stdlib; #[macro_use] extern crate alloc_no_stdlib; extern crate core; use core::ops; pub use alloc_stdlib::{HeapAlloc, StandardAlloc}; use alloc_stdlib::HeapPrealloc; mod tests; extern { fn calloc(n_elem : usize, el_size : usize) -> *mut u8; } extern { fn free(ptr : *mut u8); } //use alloc::AllocatedSlice; use alloc_no_stdlib::SliceWrapper; use alloc_no_stdlib::SliceWrapperMut; use alloc_no_stdlib::AllocatedStackMemory; use alloc_no_stdlib::Allocator; use alloc_no_stdlib::StackAllocator; use alloc_no_stdlib::bzero; declare_stack_allocator_struct!(CallocAllocatedFreelist4, 4, calloc); declare_stack_allocator_struct!(StackAllocatedFreelist16, 16, stack); fn show_heap_prealloc() { let mut zero_global_buffer = define_allocator_memory_pool!(4, u8, [0; 1024 * 1024 * 20], heap); let mut boxallocator = HeapPrealloc::::new_allocator(1024 * 1024, &mut zero_global_buffer, bzero); { let mut x = boxallocator.alloc_cell(9999); x.slice_mut()[0] = 3; let mut y = boxallocator.alloc_cell(4); y[0] = 5; boxallocator.free_cell(y); let mut three = boxallocator.alloc_cell(3); three[0] = 6; boxallocator.free_cell(three); let mut z = boxallocator.alloc_cell(4); z.slice_mut()[1] = 8; let mut reget_three = boxallocator.alloc_cell(4); reget_three.slice_mut()[1] = 9; //y.mem[0] = 6; // <-- this is an error (use after free) println!("x[0] = {:?} z[0] = {:?} z[1] = {:?} r3[0] = {:?} r3[1] = {:?}", x.mem[0], z.mem[0], z.mem[1], reget_three[0], reget_three.slice()[1]); let mut _z = boxallocator.alloc_cell(1); } } fn main() { let mut global_buffer = unsafe {define_allocator_memory_pool!(4, u8, [0; 1024 * 1024 * 200], calloc)}; { let gbref = &mut global_buffer; { let mut ags = CallocAllocatedFreelist4::::new_allocator(gbref.data, bzero); { let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; let mut y = ags.alloc_cell(4); y[0] = 5; ags.free_cell(y); let mut three = ags.alloc_cell(3); three[0] = 6; ags.free_cell(three); let mut z = ags.alloc_cell(4); z.slice_mut()[1] = 8; let mut reget_three = ags.alloc_cell(4); reget_three.slice_mut()[1] = 9; //y.mem[0] = 6; // <-- this is an error (use after free) println!("x[0] = {:?} z[0] = {:?} z[1] = {:?} r3[0] = {:?} r3[1] = {:?}", x.mem[0], z.mem[0], z.mem[1], reget_three[0], reget_three.slice()[1]); let mut _z = ags.alloc_cell(1); } } } let mut stack_global_buffer = define_allocator_memory_pool!(16, u8, [0; 1024 * 1024], stack); let mut stackallocator = StackAllocatedFreelist16::::new_allocator(&mut stack_global_buffer, bzero); { let mut x = stackallocator.alloc_cell(9999); x.slice_mut()[0] = 3; let mut y = stackallocator.alloc_cell(4); y[0] = 5; stackallocator.free_cell(y); let mut three = stackallocator.alloc_cell(3); three[0] = 6; stackallocator.free_cell(three); let mut z = stackallocator.alloc_cell(4); z.slice_mut()[1] = 8; let mut reget_three = stackallocator.alloc_cell(4); reget_three.slice_mut()[1] = 9; //y.mem[0] = 6; // <-- this is an error (use after free) println!("x[0] = {:?} z[0] = {:?} z[1] = {:?} r3[0] = {:?} r3[1] = {:?}", x.mem[0], z.mem[0], z.mem[1], reget_three[0], reget_three.slice()[1]); let mut _z = stackallocator.alloc_cell(1); } let mut halloc = HeapAlloc::::default(); for _i in 1..10 { // heap test let mut x = halloc.alloc_cell(100000); x.slice_mut()[0] = 4; let mut y = halloc.alloc_cell(110000); y.slice_mut()[0] = 5; let mut z = halloc.alloc_cell(120000); z.slice_mut()[0] = 6; halloc.free_cell(y); println!("x[0] {:?} x[9] {:?} y[0] {:?} z[0] {:?}", x.slice()[0], x.slice()[9], -999, z.slice()[0]); } show_heap_prealloc(); } alloc-stdlib-0.2.2/src/bin/tests.rs000075500000000000000000000046141046102023000152550ustar 00000000000000#![allow(unused_imports)] #[cfg(test)] extern crate core; use alloc_no_stdlib::{Allocator, SliceWrapper, SliceWrapperMut}; use super::{HeapAlloc, StandardAlloc}; #[cfg(feature="unsafe")] use alloc_stdlib::HeapAllocUninitialized; #[test] fn heap_test() { let mut halloc : HeapAlloc = HeapAlloc::{default_value: 0}; for _i in 1..10 { // heap test let mut x = halloc.alloc_cell(100000); x.slice_mut()[0] = 4; let mut y = halloc.alloc_cell(110000); y.slice_mut()[0] = 5; let mut z = halloc.alloc_cell(120000); z.slice_mut()[0] = 6; assert_eq!(y.slice()[0], 5); halloc.free_cell(y); assert_eq!(x.slice()[0], 4); assert_eq!(x.slice()[9], 0); assert_eq!(z.slice()[0], 6); } } #[test] fn std_test() { let mut halloc = StandardAlloc::default(); for _i in 1..10 { // heap test let mut x = >::alloc_cell(&mut halloc, 100000); x.slice_mut()[0] = 4; let mut y = >::alloc_cell(&mut halloc, 110000); y.slice_mut()[0] = 5; let mut z = >::alloc_cell(&mut halloc, 120000); z.slice_mut()[0] = 6; assert_eq!(y.slice()[0], 5); halloc.free_cell(y); assert_eq!(x.slice()[0], 4); assert_eq!(x.slice()[9], 0); assert_eq!(z.slice()[0], 6); } } #[cfg(feature="unsafe")] #[test] fn std_unsafe_heap_test() { let mut halloc = unsafe{HeapAllocUninitialized::::new()}; for _i in 1..10 { // heap test let mut x = halloc.alloc_cell(100000); x.slice_mut()[0] = 4; let mut y = halloc.alloc_cell(110000); y.slice_mut()[0] = 5; let mut z = halloc.alloc_cell(120000); z.slice_mut()[0] = 6; assert_eq!(y.slice()[0], 5); halloc.free_cell(y); assert_eq!(x.slice()[0], 4); assert_eq!(x.slice()[9], 0); assert_eq!(z.slice()[0], 6); } } #[cfg(feature="stdlib")] #[test] fn std_heap_test() { let mut halloc = HeapAlloc::::new(0); for _i in 1..10 { // heap test let mut x = halloc.alloc_cell(100000); x.slice_mut()[0] = 4; let mut y = halloc.alloc_cell(110000); y.slice_mut()[0] = 5; let mut z = halloc.alloc_cell(120000); z.slice_mut()[0] = 6; assert_eq!(y.slice()[0], 5); halloc.free_cell(y); assert_eq!(x.slice()[0], 4); assert_eq!(x.slice()[9], 0); assert_eq!(z.slice()[0], 6); } } alloc-stdlib-0.2.2/src/heap_alloc.rs000075500000000000000000000067421046102023000154360ustar 00000000000000use std; use super::{SliceWrapper, SliceWrapperMut, Allocator}; use std::ops; use std::ops::Range; use std::boxed::Box; use std::vec::Vec; pub struct WrapBox(std::boxed::Box<[T]>); impl From> for WrapBox { fn from(data: Vec) -> Self { WrapBox(data.into_boxed_slice()) } } impl Into> for WrapBox { fn into(self) -> Box<[T]> { self.0 } } impl Default for WrapBox { fn default() -> Self { let v : std::vec::Vec = std::vec::Vec::new(); let b = v.into_boxed_slice(); return WrapBox::(b); } } impl super::SliceWrapper for WrapBox { fn slice(&self) -> & [T] { return &*self.0 } } impl super::SliceWrapperMut for WrapBox { fn slice_mut(&mut self) -> &mut [T] { return &mut*self.0 } } impl ops::Index for WrapBox { type Output = T; fn index(&self, index: usize) -> &T { &(*self.0)[index] } } impl ops::IndexMut for WrapBox { fn index_mut(&mut self, index: usize) -> &mut T { &mut (*self.0)[index] } } impl ops::Index> for WrapBox { type Output = [T]; fn index(&self, index: Range) -> &[T] { &(*self.0)[index] } } impl ops::IndexMut> for WrapBox { fn index_mut(&mut self, index: Range) -> &mut [T] { &mut (*self.0)[index] } } pub struct HeapAlloc{ pub default_value : T, } impl Default for HeapAlloc { fn default() -> Self { Self::new(T::default()) } } impl HeapAlloc { pub fn new(data : T) -> HeapAlloc { return HeapAlloc::{default_value : data}; } } impl super::Allocator for HeapAlloc { type AllocatedMemory = WrapBox; fn alloc_cell(self : &mut HeapAlloc, len : usize) -> WrapBox { let v : std::vec::Vec = vec![self.default_value.clone();len]; let b = v.into_boxed_slice(); return WrapBox::(b); } fn free_cell(self : &mut HeapAlloc, _data : WrapBox) { } } #[deprecated] pub type HeapAllocUninitialized = HeapAlloc; pub struct HeapPrealloc<'a, T : 'a> { freelist : std::boxed::Box<[&'a mut [T]]>, } define_stack_allocator_traits!(HeapPrealloc, heap); impl<'a, T : Clone+'a> HeapPrealloc<'a, T> { fn make_freelist(freelist_size : usize) -> std::boxed::Box<[&'a mut[T]]> { let mut retval = Vec::<&'a mut[T]>::with_capacity(freelist_size); for _i in 0..freelist_size { retval.push(&mut[]); } return retval.into_boxed_slice(); } pub fn new_allocator(freelist_size : usize, memory_pool : &'a mut Box<[T]>, initializer : fn(&mut[T])) -> super::StackAllocator<'a, T, HeapPrealloc<'a, T> > { let mut retval = super::StackAllocator:: > { nop : &mut [], system_resources : HeapPrealloc:: { freelist : Self::make_freelist(freelist_size), }, free_list_start : freelist_size, free_list_overflow_count : 0, initialize : initializer, }; retval.free_cell(super::AllocatedStackMemory::{mem:&mut*memory_pool}); return retval; } #[cfg(feature="unsafe")] pub unsafe fn new_uninitialized_memory_pool(len : usize) -> Box<[T]> { let mut v : std::vec::Vec = std::vec::Vec::with_capacity(len); v.set_len(len); return v.into_boxed_slice(); } } alloc-stdlib-0.2.2/src/lib.rs000064400000000000000000000005741046102023000141070ustar 00000000000000#[macro_use] extern crate alloc_no_stdlib; pub mod heap_alloc; pub mod std_alloc; pub use self::heap_alloc::{HeapAlloc, HeapPrealloc}; pub use self::std_alloc::{StandardAlloc}; pub use alloc_no_stdlib::{Allocator, SliceWrapper, SliceWrapperMut}; pub use alloc_no_stdlib::{StackAllocator, AllocatedStackMemory}; #[cfg(feature="unsafe")] pub use heap_alloc::HeapAllocUninitialized; alloc-stdlib-0.2.2/src/std_alloc.rs000064400000000000000000000005751046102023000153060ustar 00000000000000use super::heap_alloc::WrapBox; use super::{Allocator}; #[derive(Default, Clone, Copy, Debug)] pub struct StandardAlloc{} impl Allocator for StandardAlloc { type AllocatedMemory = WrapBox; fn alloc_cell(&mut self, len : usize) -> WrapBox { vec![T::default().clone();len].into() } fn free_cell(&mut self, _data : WrapBox) { } } alloc-stdlib-0.2.2/src/test.rs000075500000000000000000000051001046102023000143110ustar 00000000000000#![cfg(test)] use super::{SliceWrapperMut, SliceWrapper}; use std::vec::Vec; use core; use super::super::Allocator; #[derive(Debug)] pub struct ItemVec(Vec); define_index_ops_mut!(T, ItemVec); impl Default for ItemVec { fn default() -> Self { ItemVec(Vec::::new()) } } impl SliceWrapper for ItemVec { fn slice(&self) -> &[Item] { &self.0[..] } } impl SliceWrapperMut for ItemVec { fn slice_mut(&mut self) -> &mut [Item] { &mut self.0[..] } } /* impl core::ops::Index for ItemVec { type Output = Item; fn index(&self, index:usize) -> &Item { &self.0[index] } } impl core::ops::IndexMut for ItemVec { fn index_mut(&mut self, index:usize) -> &mut Item { &mut self.0[index] } } */ #[derive(Default)] struct ItemVecAllocator { _item: core::marker::PhantomData, } impl Allocator for ItemVecAllocator { type AllocatedMemory = ItemVec; fn alloc_cell(&mut self, size:usize) ->ItemVec{ //eprint!("A:{}\n", size); ItemVec(vec![Item::default();size]) } fn free_cell(&mut self, _bv:ItemVec) { //eprint!("F:{}\n", _bv.slice().len()); } } #[derive(Copy,Clone)] pub struct SliceReference<'a, T:'a> { data: &'a[T], start: usize, len: usize, } impl<'a, T:'a> SliceReference<'a, T> { pub fn new(input: &'a[T], start: usize, len: usize) -> SliceReference<'a, T> { SliceReference:: { data: input.split_at(start).1.split_at(len).0, start: start, len: len, } } } impl<'a, T:'a> SliceWrapper for SliceReference<'a, T> { fn slice(&self) -> &[T]{ self.data } } impl<'a, T> Default for SliceReference<'a, T> { fn default() ->SliceReference<'a, T> { SliceReference:: { data:&[], start:0, len:0, } } } define_index_ops!(a, T, SliceReference<'a, T>); #[test] fn test_index_ops() { let array = [255u8, 0u8, 1u8,2u8,3u8,4u8,5u8, 6u8]; let sl = SliceReference::::new(&array[..], 1, 5); let val = sl[0]; assert_eq!(val, 0); assert_eq!(&sl[1..5], &[1u8,2u8,3u8,4u8]); let mut al =ItemVecAllocator::::default(); let mut dat = al.alloc_cell(1024); dat[0] = 0; dat[1] = 1; dat[2] = 2; dat[3] = 3; assert_eq!(dat[1], 1); assert_eq!(&dat[1..5], &[1u64,2u64,3u64,0u64]); assert_eq!(dat.len(), 1024); al.free_cell(dat); } alloc-stdlib-0.2.2/tests/lib.rs000075500000000000000000000314341046102023000144640ustar 00000000000000#![allow(unused_imports)] #![allow(dead_code)] //#![feature(trace_macros)] #[cfg(test)] #[macro_use] extern crate alloc_no_stdlib; extern crate alloc_stdlib; extern crate core; use core::ops; use alloc_no_stdlib::{Allocator, SliceWrapperMut, SliceWrapper, StackAllocator, AllocatedStackMemory, uninitialized, bzero}; use alloc_stdlib::{HeapPrealloc, HeapAlloc}; #[cfg(feature="unsafe")] use alloc_stdlib::{HeapAllocUninitialized}; declare_stack_allocator_struct!(CallocAllocatedFreelist4096, 4096, calloc); declare_stack_allocator_struct!(StackAllocatedFreelist4, 4, stack); declare_stack_allocator_struct!(StackAllocatedFreelist8, 8, stack); declare_stack_allocator_struct!(GlobalAllocatedFreelist, 16, global); //trace_macros!(true); define_allocator_memory_pool!(16, u8, [0; 1024 * 1024 * 100], global, global_buffer); define_allocator_memory_pool!(16, u8, [0; 1024 * 1024 * 100], global, global_buffer2); extern { fn calloc(n_elem : usize, el_size : usize) -> *mut u8; fn malloc(len : usize) -> *mut u8; fn free(item : *mut u8); } #[test] fn uninitialized_stack_pool_test() { { let mut stack_global_buffer = define_allocator_memory_pool!(4, u8, [0; 65536], stack); let mut ags = StackAllocatedFreelist4::::new_allocator(&mut stack_global_buffer, uninitialized); { let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; let mut y = ags.alloc_cell(4); y[0] = 5; ags.free_cell(y); let mut three = ags.alloc_cell(3); three[0] = 6; ags.free_cell(three); let mut z = ags.alloc_cell(4); z.slice_mut()[1] = 8; let mut reget_three = ags.alloc_cell(4); reget_three.slice_mut()[1] = 9; //y.mem[0] = 6; // <-- this is an error (use after free) assert_eq!(x[0], 4); assert_eq!(z[0], 6); assert_eq!(z[1], 8); assert_eq!(reget_three[0], 0); assert_eq!(reget_three[1], 9); let mut _z = ags.alloc_cell(1); } } } #[test] fn uninitialized_stack_pool_free_null() { let mut stack_global_buffer = define_allocator_memory_pool!(8, u8, [0; 256 - 8], stack); let mut ags = StackAllocatedFreelist8::::new_allocator(&mut stack_global_buffer, uninitialized); { let s = ags.alloc_cell(0); //u.slice_mut()[0] = 4; let t = ags.alloc_cell(0); //u.slice_mut()[0] = 4; let u = ags.alloc_cell(0); //u.slice_mut()[0] = 4; let v = ags.alloc_cell(0); //v.slice_mut()[0] = 4; let ss = ags.alloc_cell(0); //u.slice_mut()[0] = 4; let tt = ags.alloc_cell(0); //u.slice_mut()[0] = 4; let uu = ags.alloc_cell(0); //u.slice_mut()[0] = 4; let vv = ags.alloc_cell(0); //v.slice_mut()[0] = 4; let mut w = ags.alloc_cell(31); w.slice_mut()[30] = 4; let mut x = ags.alloc_cell(31); x.slice_mut()[30] = 4; let mut y = ags.alloc_cell(31); y.slice_mut()[30] = 4; let mut z = ags.alloc_cell(31); z.slice_mut()[30] = 4; let mut zz = ags.alloc_cell(31); zz.slice_mut()[30] = 4; let mut xx = ags.alloc_cell(31); xx.slice_mut()[30] = 4; let mut yy = ags.alloc_cell(31); yy.slice_mut()[30] = 4; let mut ww = ags.alloc_cell(31); ww.slice_mut()[30] = 4; ags.free_cell(y); ags.free_cell(x); ags.free_cell(z); ags.free_cell(zz); ags.free_cell(xx); ags.free_cell(yy); ags.free_cell(ww); ags.free_cell(v); ags.free_cell(u); ags.free_cell(s); ags.free_cell(t); ags.free_cell(w); ags.free_cell(vv); ags.free_cell(uu); ags.free_cell(ss); ags.free_cell(tt); let mut a = ags.alloc_cell(31); a.slice_mut()[30] = 4; let mut b = ags.alloc_cell(31); b.slice_mut()[30] = 4; let mut c = ags.alloc_cell(31); c.slice_mut()[30] = 4; let mut d = ags.alloc_cell(31); d.slice_mut()[30] = 4; let mut e = ags.alloc_cell(31); e.slice_mut()[30] = 4; let mut f = ags.alloc_cell(31); f.slice_mut()[30] = 4; let mut g = ags.alloc_cell(31); g.slice_mut()[30] = 4; let mut h = ags.alloc_cell(31); h.slice_mut()[30] = 4; } } #[test] #[cfg(all(feature="unsafe",not(feature="no-stdlib")))] fn uninitialized_heap_pool_test() { { let mut heap_global_buffer = unsafe{HeapPrealloc::::new_uninitialized_memory_pool(6 * 1024 * 1024)}; let mut ags = HeapPrealloc::::new_allocator(4096, &mut heap_global_buffer, uninitialized); { let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; let mut y = ags.alloc_cell(4); y[0] = 5; ags.free_cell(y); let mut three = ags.alloc_cell(3); three[0] = 6; ags.free_cell(three); let mut z = ags.alloc_cell(4); z.slice_mut()[1] = 8; let mut reget_three = ags.alloc_cell(4); reget_three.slice_mut()[1] = 9; //y.mem[0] = 6; // <-- this is an error (use after free) assert_eq!(x[0], 4); assert_eq!(z[0], 6); assert_eq!(z[1], 8); // assert_eq!(reget_three[0], 0); // not valid: uninitialized heap memory assert_eq!(reget_three[1], 9); let mut _z = ags.alloc_cell(1); } } } #[test] fn uninitialized_calloc_pool_test() { { let mut calloc_global_buffer = unsafe{define_allocator_memory_pool!(4096, u8, [0; 200 * 1024 * 1024], calloc)}; let mut ags = CallocAllocatedFreelist4096::::new_allocator(&mut calloc_global_buffer.data, uninitialized); { let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; let mut y = ags.alloc_cell(4); y[0] = 5; ags.free_cell(y); let mut three = ags.alloc_cell(3); three[0] = 6; ags.free_cell(three); let mut z = ags.alloc_cell(4); z.slice_mut()[1] = 8; let mut reget_three = ags.alloc_cell(4); reget_three.slice_mut()[1] = 9; //y.mem[0] = 6; // <-- this is an error (use after free) assert_eq!(x[0], 4); assert_eq!(z[0], 6); assert_eq!(z[1], 8); assert_eq!(reget_three[0], 0); // since we have control over this buffer and the free strategy: this should be zero assert_eq!(reget_three[1], 9); let mut _z = ags.alloc_cell(1); } println!("{:?}", ags.free_list_start); } } #[test] fn uninitialized_global_pool_test() { { let mut ags = GlobalAllocatedFreelist::::new_allocator(uninitialized); unsafe { bind_global_buffers_to_allocator!(ags, global_buffer, u8); } { let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; let mut y = ags.alloc_cell(4); y[0] = 5; ags.free_cell(y); let mut three = ags.alloc_cell(3); three[0] = 6; ags.free_cell(three); let mut z = ags.alloc_cell(4); z.slice_mut()[1] = 8; let mut reget_three = ags.alloc_cell(4); reget_three.slice_mut()[1] = 9; //y.mem[0] = 6; // <-- this is an error (use after free) assert_eq!(x[0], 4); assert_eq!(z[0], 6); assert_eq!(z[1], 8); assert_eq!(reget_three[0], 0); assert_eq!(reget_three[1], 9); let mut _z = ags.alloc_cell(1); } } } #[test] fn stack_pool_test() { { let mut stack_global_buffer = define_allocator_memory_pool!(4, u8, [0; 65536], stack); let mut ags = StackAllocatedFreelist4::::new_allocator(&mut stack_global_buffer, bzero); { let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; let mut y = ags.alloc_cell(4); y[0] = 5; ags.free_cell(y); let mut three = ags.alloc_cell(3); three[0] = 6; ags.free_cell(three); let mut z = ags.alloc_cell(4); z.slice_mut()[1] = 8; let mut reget_three = ags.alloc_cell(4); reget_three.slice_mut()[1] = 9; //y.mem[0] = 6; // <-- this is an error (use after free) assert_eq!(x[0], 4); assert_eq!(z[0], 0); assert_eq!(z[1], 8); assert_eq!(reget_three[0], 0); assert_eq!(reget_three[1], 9); let mut _z = ags.alloc_cell(1); } } } #[test] fn stack_pool_free_null() { let mut stack_global_buffer = define_allocator_memory_pool!(8, u8, [0; 256 - 8], stack); let mut ags = StackAllocatedFreelist8::::new_allocator(&mut stack_global_buffer, bzero); { let s = ags.alloc_cell(0); //u.slice_mut()[0] = 4; let t = ags.alloc_cell(0); //u.slice_mut()[0] = 4; let u = ags.alloc_cell(0); //u.slice_mut()[0] = 4; let v = ags.alloc_cell(0); //v.slice_mut()[0] = 4; let ss = ags.alloc_cell(0); //u.slice_mut()[0] = 4; let tt = ags.alloc_cell(0); //u.slice_mut()[0] = 4; let uu = ags.alloc_cell(0); //u.slice_mut()[0] = 4; let vv = ags.alloc_cell(0); //v.slice_mut()[0] = 4; let mut w = ags.alloc_cell(31); w.slice_mut()[30] = 4; let mut x = ags.alloc_cell(31); x.slice_mut()[30] = 4; let mut y = ags.alloc_cell(31); y.slice_mut()[30] = 4; let mut z = ags.alloc_cell(31); z.slice_mut()[30] = 4; let mut zz = ags.alloc_cell(31); zz.slice_mut()[30] = 4; let mut xx = ags.alloc_cell(31); xx.slice_mut()[30] = 4; let mut yy = ags.alloc_cell(31); yy.slice_mut()[30] = 4; let mut ww = ags.alloc_cell(31); ww.slice_mut()[30] = 4; ags.free_cell(y); ags.free_cell(x); ags.free_cell(z); ags.free_cell(zz); ags.free_cell(xx); ags.free_cell(yy); ags.free_cell(ww); ags.free_cell(v); ags.free_cell(u); ags.free_cell(s); ags.free_cell(t); ags.free_cell(w); ags.free_cell(vv); ags.free_cell(uu); ags.free_cell(ss); ags.free_cell(tt); let mut a = ags.alloc_cell(31); a.slice_mut()[30] = 4; let mut b = ags.alloc_cell(31); b.slice_mut()[30] = 4; let mut c = ags.alloc_cell(31); c.slice_mut()[30] = 4; let mut d = ags.alloc_cell(31); d.slice_mut()[30] = 4; let mut e = ags.alloc_cell(31); e.slice_mut()[30] = 4; let mut f = ags.alloc_cell(31); f.slice_mut()[30] = 4; let mut g = ags.alloc_cell(31); g.slice_mut()[30] = 4; let mut h = ags.alloc_cell(31); h.slice_mut()[30] = 4; } } #[test] #[cfg(not(feature="no-stdlib"))] fn heap_pool_test() { { let mut heap_global_buffer = define_allocator_memory_pool!(4096, u8, [0; 6 * 1024 * 1024], heap); let mut ags = HeapPrealloc::::new_allocator(4096, &mut heap_global_buffer, bzero); { let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; let mut y = ags.alloc_cell(4); y[0] = 5; ags.free_cell(y); let mut three = ags.alloc_cell(3); three[0] = 6; ags.free_cell(three); let mut z = ags.alloc_cell(4); z.slice_mut()[1] = 8; let mut reget_three = ags.alloc_cell(4); reget_three.slice_mut()[1] = 9; //y.mem[0] = 6; // <-- this is an error (use after free) assert_eq!(x[0], 4); assert_eq!(z[0], 0); assert_eq!(z[1], 8); assert_eq!(reget_three[0], 0); assert_eq!(reget_three[1], 9); let mut _z = ags.alloc_cell(1); } } } #[test] fn calloc_pool_test() { { let mut calloc_global_buffer = unsafe {define_allocator_memory_pool!(4096, u8, [0; 200 * 1024 * 1024], calloc)}; { let mut ags = CallocAllocatedFreelist4096::::new_allocator(&mut calloc_global_buffer.data, bzero); { let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; let mut y = ags.alloc_cell(4); y[0] = 5; ags.free_cell(y); let mut three = ags.alloc_cell(3); three[0] = 6; ags.free_cell(three); let mut z = ags.alloc_cell(4); z.slice_mut()[1] = 8; let mut reget_three = ags.alloc_cell(4); reget_three.slice_mut()[1] = 9; //y.mem[0] = 6; // <-- this is an error (use after free) assert_eq!(x[0], 4); assert_eq!(z[0], 0); assert_eq!(z[1], 8); assert_eq!(reget_three[0], 0); assert_eq!(reget_three[1], 9); let mut _z = ags.alloc_cell(1); } } { let mut ags = CallocAllocatedFreelist4096::::new_allocator(&mut calloc_global_buffer.data, bzero); { let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; let mut y = ags.alloc_cell(4); y[0] = 5; ags.free_cell(y); let mut three = ags.alloc_cell(3); three[0] = 6; ags.free_cell(three); let mut z = ags.alloc_cell(4); z.slice_mut()[1] = 8; let mut reget_three = ags.alloc_cell(4); reget_three.slice_mut()[1] = 9; //y.mem[0] = 6; // <-- this is an error (use after free) assert_eq!(x[0], 4); assert_eq!(z[0], 0); assert_eq!(z[1], 8); assert_eq!(reget_three[0], 0); assert_eq!(reget_three[1], 9); let mut _z = ags.alloc_cell(1); } } drop(calloc_global_buffer); } } #[test] fn global_pool_test() { { let mut ags = GlobalAllocatedFreelist::::new_allocator(bzero); unsafe { bind_global_buffers_to_allocator!(ags, global_buffer2, u8); } { let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; let mut y = ags.alloc_cell(4); y[0] = 5; ags.free_cell(y); let mut three = ags.alloc_cell(3); three[0] = 6; ags.free_cell(three); let mut z = ags.alloc_cell(4); z.slice_mut()[1] = 8; let mut reget_three = ags.alloc_cell(4); reget_three.slice_mut()[1] = 9; //y.mem[0] = 6; // <-- this is an error (use after free) assert_eq!(x[0], 4); assert_eq!(z[0], 0); assert_eq!(z[1], 8); assert_eq!(reget_three[0], 0); assert_eq!(reget_three[1], 9); let mut _z = ags.alloc_cell(1); } } }