├── .gitignore ├── src ├── allocator.rs ├── allocated_memory │ ├── mod.rs │ └── index_macro.rs ├── allocated_stack_memory.rs ├── bin │ ├── heap_alloc.rs │ ├── tests.rs │ └── example.rs ├── tests.rs ├── lib.rs ├── stack_allocator.rs └── init.rs ├── alloc-stdlib ├── src │ ├── lib.rs │ ├── std_alloc.rs │ ├── bin │ │ ├── tests.rs │ │ └── example.rs │ ├── test.rs │ └── heap_alloc.rs ├── Cargo.toml ├── README.md └── tests │ └── lib.rs ├── .travis.yml ├── Cargo.toml ├── LICENSE ├── README.md └── tests └── lib.rs /.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | -------------------------------------------------------------------------------- /src/allocator.rs: -------------------------------------------------------------------------------- 1 | 2 | pub trait Allocator { 3 | type AllocatedMemory : super::AllocatedSlice; 4 | fn alloc_cell(&mut self, len : usize) -> Self::AllocatedMemory; 5 | fn free_cell(&mut self, data : Self::AllocatedMemory); 6 | } 7 | 8 | -------------------------------------------------------------------------------- /alloc-stdlib/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate alloc_no_stdlib; 3 | pub mod heap_alloc; 4 | pub mod std_alloc; 5 | pub use self::heap_alloc::{HeapAlloc, HeapPrealloc}; 6 | pub use self::std_alloc::{StandardAlloc}; 7 | pub use alloc_no_stdlib::{Allocator, SliceWrapper, SliceWrapperMut}; 8 | pub use alloc_no_stdlib::{StackAllocator, AllocatedStackMemory}; 9 | #[cfg(feature="unsafe")] 10 | pub use heap_alloc::HeapAllocUninitialized; 11 | -------------------------------------------------------------------------------- /alloc-stdlib/src/std_alloc.rs: -------------------------------------------------------------------------------- 1 | use super::heap_alloc::WrapBox; 2 | use super::{Allocator}; 3 | #[derive(Default, Clone, Copy, Debug)] 4 | pub struct StandardAlloc{} 5 | 6 | impl Allocator for StandardAlloc { 7 | type AllocatedMemory = WrapBox; 8 | fn alloc_cell(&mut self, len : usize) -> WrapBox { 9 | vec![T::default().clone();len].into() 10 | } 11 | fn free_cell(&mut self, _data : WrapBox) { 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | rust: 3 | - nightly 4 | - stable 5 | - 1.12.0 6 | - 1.8.0 7 | 8 | os: 9 | - linux 10 | - osx 11 | 12 | script: 13 | - cargo test 14 | - cargo test --features=unsafe --release 15 | - cd alloc-stdlib && cargo test && cd .. 16 | - cd alloc-stdlib && cargo test --release --features=unsafe && cd .. 17 | - cd alloc-stdlib && cargo test --release && cd .. 18 | 19 | matrix: 20 | exclude: 21 | - rust: 1.8.0 22 | os: osx 23 | -------------------------------------------------------------------------------- /src/allocated_memory/mod.rs: -------------------------------------------------------------------------------- 1 | extern crate core; 2 | #[macro_use] 3 | mod index_macro; 4 | use core::default::Default; 5 | pub use core::ops::IndexMut; 6 | pub use core::ops::Index; 7 | pub use core::ops::Range; 8 | pub trait SliceWrapper { 9 | fn slice(& self) -> & [T]; 10 | fn len(&self) -> usize{ 11 | self.slice().len() 12 | } 13 | } 14 | 15 | pub trait SliceWrapperMut : SliceWrapper { 16 | fn slice_mut (&mut self) -> & mut [T]; 17 | } 18 | 19 | pub trait AllocatedSlice 20 | : SliceWrapperMut + SliceWrapper + Default { 21 | } 22 | 23 | impl AllocatedSlice for U where U : SliceWrapperMut + SliceWrapper + Default { 24 | 25 | } 26 | -------------------------------------------------------------------------------- /alloc-stdlib/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "alloc-stdlib" 3 | description = "A dynamic allocator example that may be used with the stdlib" 4 | version = "0.2.2" 5 | authors = ["Daniel Reiter Horn "] 6 | documentation = "https://raw.githubusercontent.com/dropbox/rust-alloc-no-stdlib/master/alloc-stdlib/tests/lib.rs" 7 | homepage = "https://github.com/dropbox/rust-alloc-no-stdlib" 8 | readme = "README.md" 9 | keywords = ["custom", "allocator", "calloc", "safe", "nostd"] 10 | license = "BSD-3-Clause" 11 | repository = "https://github.com/dropbox/rust-alloc-no-stdlib" 12 | autobins = false 13 | 14 | [[bin]] 15 | name = "example" 16 | 17 | [dependencies] 18 | "alloc-no-stdlib" = { version="2.0.4", path="../"} 19 | 20 | [features] 21 | unsafe = [] 22 | -------------------------------------------------------------------------------- /src/allocated_stack_memory.rs: -------------------------------------------------------------------------------- 1 | extern crate core; 2 | 3 | use super::allocated_memory::SliceWrapper; 4 | use super::allocated_memory::SliceWrapperMut; 5 | 6 | pub struct AllocatedStackMemory<'a, T:'a> { 7 | pub mem : &'a mut [T], 8 | } 9 | 10 | define_index_ops_mut!(a, T, AllocatedStackMemory<'a, T>); 11 | 12 | impl<'a, T: 'a> core::default::Default for AllocatedStackMemory<'a, T> { 13 | fn default() -> Self { 14 | return AllocatedStackMemory::<'a, T>{mem : &mut[]}; 15 | } 16 | } 17 | 18 | 19 | impl<'a, T: 'a> SliceWrapper for AllocatedStackMemory<'a, T> { 20 | fn slice(& self) -> & [T] { 21 | return & self.mem; 22 | } 23 | } 24 | 25 | impl<'a, T: 'a> SliceWrapperMut for AllocatedStackMemory<'a, T> { 26 | fn slice_mut(& mut self) ->& mut [T] { 27 | return &mut self.mem; 28 | } 29 | } 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "alloc-no-stdlib" 3 | description = "A dynamic allocator that may be used with or without the stdlib. This allows a package with nostd to allocate memory dynamically and be used either with a custom allocator, items on the stack, or by a package that wishes to simply use Box<>. It also provides options to use calloc or a mutable global variable for pre-zeroed memory" 4 | version = "2.0.4" 5 | authors = ["Daniel Reiter Horn "] 6 | documentation = "https://raw.githubusercontent.com/dropbox/rust-alloc-no-stdlib/master/tests/lib.rs" 7 | homepage = "https://github.com/dropbox/rust-alloc-no-stdlib" 8 | readme = "README.md" 9 | keywords = ["custom", "allocator", "calloc", "safe", "nostd"] 10 | license = "BSD-3-Clause" 11 | repository = "https://github.com/dropbox/rust-alloc-no-stdlib" 12 | autobins = false 13 | 14 | [[bin]] 15 | name = "example" 16 | 17 | [features] 18 | unsafe = [] 19 | -------------------------------------------------------------------------------- /src/bin/heap_alloc.rs: -------------------------------------------------------------------------------- 1 | use alloc_no_stdlib; 2 | use core; 3 | use alloc_no_stdlib::{SliceWrapper, SliceWrapperMut}; 4 | 5 | pub struct Rebox { 6 | b : Box<[T]>, 7 | } 8 | 9 | impl core::default::Default for Rebox { 10 | fn default() -> Self { 11 | let v : Vec = Vec::new(); 12 | let b = v.into_boxed_slice(); 13 | return Rebox::{b : b}; 14 | } 15 | } 16 | define_index_ops_mut!(T, Rebox); 17 | 18 | impl alloc_no_stdlib::SliceWrapper for Rebox { 19 | fn slice(&self) -> & [T] { 20 | return &*self.b 21 | } 22 | } 23 | 24 | impl alloc_no_stdlib::SliceWrapperMut for Rebox { 25 | fn slice_mut(&mut self) -> &mut [T] { 26 | return &mut*self.b 27 | } 28 | } 29 | 30 | pub struct HeapAllocator{ 31 | pub default_value : T, 32 | } 33 | 34 | impl alloc_no_stdlib::Allocator for HeapAllocator { 35 | type AllocatedMemory = Rebox; 36 | fn alloc_cell(self : &mut HeapAllocator, len : usize) -> Rebox { 37 | 38 | let v : Vec = vec![self.default_value.clone();len]; 39 | let b = v.into_boxed_slice(); 40 | return Rebox::{b : b}; 41 | } 42 | fn free_cell(self : &mut HeapAllocator, _data : Rebox) { 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Dropbox, Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 13 | -------------------------------------------------------------------------------- /src/bin/tests.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused_imports)] 2 | #[cfg(test)] 3 | extern crate core; 4 | use alloc_no_stdlib::Allocator; 5 | use super::HeapAllocator; 6 | #[cfg(feature="stdlib")] 7 | use alloc_no_stdlib::HeapAlloc; 8 | #[cfg(all(feature="unsafe", feature="stdlib"))] 9 | use alloc_no_stdlib::HeapAllocUninitialized; 10 | #[test] 11 | fn heap_test() { 12 | let mut halloc : HeapAllocator = HeapAllocator::{default_value: 0}; 13 | for _i in 1..10 { // heap test 14 | let mut x = halloc.alloc_cell(100000); 15 | x[0] = 4; 16 | let mut y = halloc.alloc_cell(110000); 17 | y[0] = 5; 18 | let mut z = halloc.alloc_cell(120000); 19 | z[0] = 6; 20 | assert_eq!(y[0], 5); 21 | halloc.free_cell(y); 22 | assert_eq!(x[0], 4); 23 | assert_eq!(x[9], 0); 24 | assert_eq!(z[0], 6); 25 | } 26 | 27 | } 28 | 29 | 30 | #[cfg(all(feature="unsafe", feature="stdlib"))] 31 | #[test] 32 | fn std_unsafe_heap_test() { 33 | let mut halloc = unsafe{HeapAllocUninitialized::::new()}; 34 | for _i in 1..10 { // heap test 35 | let mut x = halloc.alloc_cell(100000); 36 | x[0] = 4; 37 | let mut y = halloc.alloc_cell(110000); 38 | y[0] = 5; 39 | let mut z = halloc.alloc_cell(120000); 40 | z[0] = 6; 41 | assert_eq!(y[0], 5); 42 | halloc.free_cell(y); 43 | assert_eq!(x[0], 4); 44 | assert_eq!(x[9], 0); 45 | assert_eq!(z[0], 6); 46 | } 47 | 48 | } 49 | 50 | #[cfg(feature="stdlib")] 51 | #[test] 52 | fn std_heap_test() { 53 | let mut halloc = HeapAlloc::::new(0); 54 | for _i in 1..10 { // heap test 55 | let mut x = halloc.alloc_cell(100000); 56 | x[0] = 4; 57 | let mut y = halloc.alloc_cell(110000); 58 | y[0] = 5; 59 | let mut z = halloc.alloc_cell(120000); 60 | z[0] = 6; 61 | assert_eq!(y[0], 5); 62 | halloc.free_cell(y); 63 | assert_eq!(x[0], 4); 64 | assert_eq!(x[9], 0); 65 | assert_eq!(z[0], 6); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/tests.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused_imports)] 2 | #![allow(dead_code)] 3 | #[cfg(test)] 4 | extern crate core; 5 | use core::ops; 6 | use super::{Allocator, SliceWrapperMut, SliceWrapper, 7 | StackAllocator, AllocatedStackMemory, CallocBackingStore}; 8 | 9 | struct StackAllocatedFreelist4<'a, T : 'a> { 10 | freelist : [&'a mut [T]; 4], 11 | } 12 | 13 | 14 | impl<'a, T: 'a> SliceWrapper<&'a mut[T]> for StackAllocatedFreelist4<'a, T> { 15 | fn slice(& self) -> & [&'a mut[T]] { 16 | return & self.freelist; 17 | } 18 | } 19 | 20 | impl<'a, T: 'a> SliceWrapperMut<&'a mut [T]> for StackAllocatedFreelist4<'a, T> { 21 | fn slice_mut(& mut self) ->&mut [&'a mut [T]] { 22 | return &mut self.freelist; 23 | } 24 | } 25 | 26 | impl<'a, T: 'a> ops::Index for StackAllocatedFreelist4<'a, T> { 27 | type Output = [T]; 28 | fn index<'b> (&'b self, _index : usize) -> &'b [T] { 29 | return &self.freelist[_index]; 30 | } 31 | } 32 | 33 | impl<'a, T: 'a> ops::IndexMut for StackAllocatedFreelist4<'a, T> { 34 | fn index_mut<'b>(&'b mut self, _index : usize) -> &'b mut [T] { 35 | return &mut self.freelist[_index]; 36 | } 37 | } 38 | 39 | 40 | #[test] 41 | fn integration_test() { 42 | let mut global_buffer : [u8; 65536] = [0; 65536]; 43 | let mut ags = StackAllocator:: > { 44 | nop : &mut [], 45 | system_resources : StackAllocatedFreelist4:: { 46 | freelist : [&mut[],&mut[],&mut[],&mut[],], 47 | }, 48 | free_list_start : 4, 49 | free_list_overflow_count : 0, 50 | initializer : bzero, 51 | }; 52 | ags.free_cell(AllocatedStackMemory::{mem:&mut global_buffer}); 53 | 54 | { 55 | let mut x = ags.alloc_cell(9999); 56 | x.slice_mut()[0] = 4; 57 | let mut y = ags.alloc_cell(4); 58 | y[0] = 5; 59 | ags.free_cell(y); 60 | 61 | let mut three = ags.alloc_cell(3); 62 | three[0] = 6; 63 | ags.free_cell(three); 64 | 65 | let mut z = ags.alloc_cell(4); 66 | z.slice_mut()[1] = 8; 67 | let mut reget_three = ags.alloc_cell(4); 68 | reget_three.slice_mut()[1] = 9; 69 | //y.mem[0] = 6; // <-- this is an error (use after free) 70 | assert_eq!(x[0], 4); 71 | assert_eq!(z[0], 6); 72 | assert_eq!(z[1], 8); 73 | assert_eq!(reget_three[0], 0); 74 | assert_eq!(reget_three[1], 9); 75 | let mut _z = ags.alloc_cell(1); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /alloc-stdlib/src/bin/tests.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused_imports)] 2 | #[cfg(test)] 3 | extern crate core; 4 | use alloc_no_stdlib::{Allocator, SliceWrapper, SliceWrapperMut}; 5 | use super::{HeapAlloc, StandardAlloc}; 6 | #[cfg(feature="unsafe")] 7 | use alloc_stdlib::HeapAllocUninitialized; 8 | #[test] 9 | fn heap_test() { 10 | let mut halloc : HeapAlloc = HeapAlloc::{default_value: 0}; 11 | for _i in 1..10 { // heap test 12 | let mut x = halloc.alloc_cell(100000); 13 | x.slice_mut()[0] = 4; 14 | let mut y = halloc.alloc_cell(110000); 15 | y.slice_mut()[0] = 5; 16 | let mut z = halloc.alloc_cell(120000); 17 | z.slice_mut()[0] = 6; 18 | assert_eq!(y.slice()[0], 5); 19 | halloc.free_cell(y); 20 | assert_eq!(x.slice()[0], 4); 21 | assert_eq!(x.slice()[9], 0); 22 | assert_eq!(z.slice()[0], 6); 23 | } 24 | 25 | } 26 | 27 | #[test] 28 | fn std_test() { 29 | let mut halloc = StandardAlloc::default(); 30 | for _i in 1..10 { // heap test 31 | let mut x = >::alloc_cell(&mut halloc, 100000); 32 | x.slice_mut()[0] = 4; 33 | let mut y = >::alloc_cell(&mut halloc, 110000); 34 | y.slice_mut()[0] = 5; 35 | let mut z = >::alloc_cell(&mut halloc, 120000); 36 | z.slice_mut()[0] = 6; 37 | assert_eq!(y.slice()[0], 5); 38 | halloc.free_cell(y); 39 | assert_eq!(x.slice()[0], 4); 40 | assert_eq!(x.slice()[9], 0); 41 | assert_eq!(z.slice()[0], 6); 42 | } 43 | 44 | } 45 | 46 | 47 | #[cfg(feature="unsafe")] 48 | #[test] 49 | fn std_unsafe_heap_test() { 50 | let mut halloc = unsafe{HeapAllocUninitialized::::new()}; 51 | for _i in 1..10 { // heap test 52 | let mut x = halloc.alloc_cell(100000); 53 | x.slice_mut()[0] = 4; 54 | let mut y = halloc.alloc_cell(110000); 55 | y.slice_mut()[0] = 5; 56 | let mut z = halloc.alloc_cell(120000); 57 | z.slice_mut()[0] = 6; 58 | assert_eq!(y.slice()[0], 5); 59 | halloc.free_cell(y); 60 | assert_eq!(x.slice()[0], 4); 61 | assert_eq!(x.slice()[9], 0); 62 | assert_eq!(z.slice()[0], 6); 63 | } 64 | 65 | } 66 | 67 | #[cfg(feature="stdlib")] 68 | #[test] 69 | fn std_heap_test() { 70 | let mut halloc = HeapAlloc::::new(0); 71 | for _i in 1..10 { // heap test 72 | let mut x = halloc.alloc_cell(100000); 73 | x.slice_mut()[0] = 4; 74 | let mut y = halloc.alloc_cell(110000); 75 | y.slice_mut()[0] = 5; 76 | let mut z = halloc.alloc_cell(120000); 77 | z.slice_mut()[0] = 6; 78 | assert_eq!(y.slice()[0], 5); 79 | halloc.free_cell(y); 80 | assert_eq!(x.slice()[0], 4); 81 | assert_eq!(x.slice()[9], 0); 82 | assert_eq!(z.slice()[0], 6); 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | 3 | #[macro_use] 4 | mod allocated_memory; 5 | mod stack_allocator; 6 | mod allocated_stack_memory; 7 | #[macro_use] 8 | pub mod init; 9 | pub use allocated_memory::SliceWrapper; 10 | pub use allocated_memory::SliceWrapperMut; 11 | pub use allocated_memory::AllocatedSlice; 12 | 13 | pub use allocated_stack_memory::AllocatedStackMemory; 14 | pub use stack_allocator::Allocator; 15 | pub use stack_allocator::StackAllocator; 16 | 17 | use core::default::Default; 18 | pub fn bzero (data : &mut [T]) { 19 | for iter in data.iter_mut() { 20 | *iter = T::default(); 21 | } 22 | } 23 | 24 | pub fn uninitialized (_data : &mut[T]) {} 25 | 26 | 27 | 28 | #[derive(Debug)] 29 | pub struct CallocBackingStore<'a, T : 'a> { 30 | pub raw_data : *mut u8, 31 | pub data : &'a mut[T], 32 | free : unsafe extern "C" fn(*mut u8), 33 | } 34 | 35 | pub enum AllocatorC { 36 | Calloc(unsafe extern "C" fn(usize, usize) -> *mut u8), 37 | Malloc(unsafe extern "C" fn(usize) -> *mut u8), 38 | Custom(fn(usize) -> *mut u8), 39 | } 40 | impl<'a, T : 'a> CallocBackingStore<'a, T> { 41 | pub unsafe fn new(num_elements : usize, alloc : AllocatorC, free : unsafe extern "C" fn (*mut u8), should_free : bool) -> Self{ 42 | let retval : *mut u8 = if num_elements == 0 {core::ptr::null_mut()} else { 43 | match alloc { 44 | AllocatorC::Calloc(calloc) => calloc(num_elements, core::mem::size_of::()), 45 | AllocatorC::Malloc(malloc) => malloc(num_elements *core::mem::size_of::()), 46 | AllocatorC::Custom(malloc) => malloc(num_elements *core::mem::size_of::()), 47 | } 48 | }; 49 | if num_elements == 0 || retval.is_null() { 50 | return CallocBackingStore::<'a, T>{ 51 | raw_data : core::ptr::null_mut(), 52 | data : &mut[], 53 | free : free, 54 | } 55 | } 56 | let raw_data : *mut T = core::mem::transmute(retval); 57 | if should_free { 58 | return CallocBackingStore::<'a, T>{ 59 | raw_data : retval, 60 | data : core::slice::from_raw_parts_mut(raw_data, 61 | num_elements), 62 | free : free, 63 | }; 64 | } else { 65 | let null_ptr : *const u8 = core::ptr::null(); 66 | return CallocBackingStore::<'a, T>{ 67 | raw_data : core::mem::transmute(null_ptr),//retval, 68 | data : core::slice::from_raw_parts_mut(raw_data, 69 | num_elements), 70 | free : free, 71 | }; 72 | } 73 | } 74 | } 75 | impl<'a, T:'a> Drop for CallocBackingStore<'a, T> { 76 | fn drop(self :&mut Self) { 77 | // core::mem::forget(core::mem::replace(self.data, &mut[])); 78 | core::mem::forget(core::mem::replace(&mut self.data, &mut[])); 79 | if !self.raw_data.is_null() { 80 | let local_free = self.free; 81 | unsafe {(local_free)(self.raw_data)}; 82 | 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /alloc-stdlib/src/test.rs: -------------------------------------------------------------------------------- 1 | #![cfg(test)] 2 | 3 | use super::{SliceWrapperMut, SliceWrapper}; 4 | use std::vec::Vec; 5 | use core; 6 | use super::super::Allocator; 7 | #[derive(Debug)] 8 | pub struct ItemVec(Vec); 9 | define_index_ops_mut!(T, ItemVec); 10 | 11 | impl Default for ItemVec { 12 | fn default() -> Self { 13 | ItemVec(Vec::::new()) 14 | } 15 | } 16 | impl SliceWrapper for ItemVec { 17 | fn slice(&self) -> &[Item] { 18 | &self.0[..] 19 | } 20 | } 21 | 22 | impl SliceWrapperMut for ItemVec { 23 | fn slice_mut(&mut self) -> &mut [Item] { 24 | &mut self.0[..] 25 | } 26 | } 27 | /* 28 | impl core::ops::Index for ItemVec { 29 | type Output = Item; 30 | fn index(&self, index:usize) -> &Item { 31 | &self.0[index] 32 | } 33 | } 34 | 35 | impl core::ops::IndexMut for ItemVec { 36 | 37 | fn index_mut(&mut self, index:usize) -> &mut Item { 38 | &mut self.0[index] 39 | } 40 | } 41 | */ 42 | #[derive(Default)] 43 | struct ItemVecAllocator { 44 | _item: core::marker::PhantomData, 45 | } 46 | impl Allocator for ItemVecAllocator { 47 | type AllocatedMemory = ItemVec; 48 | fn alloc_cell(&mut self, size:usize) ->ItemVec{ 49 | //eprint!("A:{}\n", size); 50 | ItemVec(vec![Item::default();size]) 51 | } 52 | fn free_cell(&mut self, _bv:ItemVec) { 53 | //eprint!("F:{}\n", _bv.slice().len()); 54 | } 55 | } 56 | 57 | 58 | 59 | #[derive(Copy,Clone)] 60 | pub struct SliceReference<'a, T:'a> { 61 | data: &'a[T], 62 | start: usize, 63 | len: usize, 64 | } 65 | 66 | impl<'a, T:'a> SliceReference<'a, T> { 67 | pub fn new(input: &'a[T], start: usize, len: usize) -> SliceReference<'a, T> { 68 | SliceReference:: { 69 | data: input.split_at(start).1.split_at(len).0, 70 | start: start, 71 | len: len, 72 | } 73 | } 74 | } 75 | 76 | impl<'a, T:'a> SliceWrapper for SliceReference<'a, T> { 77 | fn slice(&self) -> &[T]{ 78 | self.data 79 | } 80 | } 81 | 82 | impl<'a, T> Default for SliceReference<'a, T> { 83 | fn default() ->SliceReference<'a, T> { 84 | SliceReference:: { 85 | data:&[], 86 | start:0, 87 | len:0, 88 | } 89 | } 90 | } 91 | 92 | define_index_ops!(a, T, SliceReference<'a, T>); 93 | 94 | #[test] 95 | fn test_index_ops() { 96 | let array = [255u8, 0u8, 1u8,2u8,3u8,4u8,5u8, 6u8]; 97 | let sl = SliceReference::::new(&array[..], 1, 5); 98 | let val = sl[0]; 99 | assert_eq!(val, 0); 100 | assert_eq!(&sl[1..5], &[1u8,2u8,3u8,4u8]); 101 | let mut al =ItemVecAllocator::::default(); 102 | let mut dat = al.alloc_cell(1024); 103 | dat[0] = 0; 104 | dat[1] = 1; 105 | dat[2] = 2; 106 | dat[3] = 3; 107 | assert_eq!(dat[1], 1); 108 | assert_eq!(&dat[1..5], &[1u64,2u64,3u64,0u64]); 109 | assert_eq!(dat.len(), 1024); 110 | al.free_cell(dat); 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/bin/example.rs: -------------------------------------------------------------------------------- 1 | //#![feature(trace_macros)] 2 | #[macro_use] 3 | extern crate alloc_no_stdlib; 4 | extern crate core; 5 | use core::ops; 6 | mod heap_alloc; 7 | 8 | pub use heap_alloc::HeapAllocator; 9 | mod tests; 10 | extern { 11 | fn calloc(n_elem : usize, el_size : usize) -> *mut u8; 12 | } 13 | extern { 14 | fn free(ptr : *mut u8); 15 | } 16 | 17 | 18 | //use alloc::AllocatedSlice; 19 | use alloc_no_stdlib::SliceWrapper; 20 | use alloc_no_stdlib::SliceWrapperMut; 21 | use alloc_no_stdlib::AllocatedStackMemory; 22 | use alloc_no_stdlib::Allocator; 23 | use alloc_no_stdlib::StackAllocator; 24 | 25 | use alloc_no_stdlib::bzero; 26 | declare_stack_allocator_struct!(CallocAllocatedFreelist4, 4, calloc); 27 | declare_stack_allocator_struct!(StackAllocatedFreelist16, 16, stack); 28 | #[repr(C)] 29 | 30 | #[derive(PartialEq, Copy, Clone, Debug)] 31 | pub struct HuffmanCode { 32 | pub value: u16, // symbol value or table offset 33 | pub bits: u8, // number of bits used for this symbol 34 | } 35 | 36 | 37 | impl Default for HuffmanCode { 38 | fn default() -> Self { 39 | HuffmanCode { 40 | value: 0, 41 | bits: 0, 42 | } 43 | } 44 | } 45 | 46 | fn main() { 47 | 48 | let mut global_buffer = unsafe {define_allocator_memory_pool!(4, u8, [0; 1024 * 1024 * 200], calloc)}; 49 | { 50 | let gbref = &mut global_buffer; 51 | { 52 | let mut ags = CallocAllocatedFreelist4::::new_allocator(gbref.data, bzero); 53 | 54 | { 55 | let mut x = ags.alloc_cell(9999); 56 | x.slice_mut()[0] = 4; 57 | let mut y = ags.alloc_cell(4); 58 | y[0] = 5; 59 | ags.free_cell(y); 60 | 61 | let mut three = ags.alloc_cell(3); 62 | three[0] = 6; 63 | ags.free_cell(three); 64 | 65 | let mut z = ags.alloc_cell(4); 66 | z.slice_mut()[1] = 8; 67 | let mut reget_three = ags.alloc_cell(4); 68 | reget_three.slice_mut()[1] = 9; 69 | //y.mem[0] = 6; // <-- this is an error (use after free) 70 | 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]); 71 | let mut _z = ags.alloc_cell(1); 72 | } 73 | } 74 | } 75 | 76 | 77 | let mut stack_global_buffer = define_allocator_memory_pool!(16, u8, [0; 1024 * 1024], stack); 78 | let mut stack_global_buffer_hc = define_allocator_memory_pool!(16, HuffmanCode, [HuffmanCode::default(); 1024 * 1024], stack); 79 | { 80 | let mut stackallocatorhc = StackAllocatedFreelist16::::new_allocator(&mut stack_global_buffer_hc, bzero); 81 | stackallocatorhc.alloc_cell(9999); 82 | } 83 | let mut stackallocator = StackAllocatedFreelist16::::new_allocator(&mut stack_global_buffer, bzero); 84 | { 85 | let mut x = stackallocator.alloc_cell(9999); 86 | x.slice_mut()[0] = 3; 87 | let mut y = stackallocator.alloc_cell(4); 88 | y[0] = 5; 89 | stackallocator.free_cell(y); 90 | 91 | let mut three = stackallocator.alloc_cell(3); 92 | three[0] = 6; 93 | stackallocator.free_cell(three); 94 | 95 | let mut z = stackallocator.alloc_cell(4); 96 | z.slice_mut()[1] = 8; 97 | let mut reget_three = stackallocator.alloc_cell(4); 98 | reget_three.slice_mut()[1] = 9; 99 | //y.mem[0] = 6; // <-- this is an error (use after free) 100 | 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]); 101 | let mut _z = stackallocator.alloc_cell(1); 102 | } 103 | 104 | let mut halloc : HeapAllocator = HeapAllocator::{default_value: 0}; 105 | for _i in 1..10 { // heap test 106 | let mut x = halloc.alloc_cell(100000); 107 | x[0] = 4; 108 | let mut y = halloc.alloc_cell(110000); 109 | y[0] = 5; 110 | let mut z = halloc.alloc_cell(120000); 111 | z[0] = 6; 112 | halloc.free_cell(y); 113 | println!("x[0] {:?} x[9] {:?} y[0] {:?} z[0] {:?}", 114 | x[0], x[9], -999, z[0]); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /alloc-stdlib/src/heap_alloc.rs: -------------------------------------------------------------------------------- 1 | use std; 2 | 3 | 4 | use super::{SliceWrapper, SliceWrapperMut, Allocator}; 5 | 6 | use std::ops; 7 | use std::ops::Range; 8 | use std::boxed::Box; 9 | use std::vec::Vec; 10 | pub struct WrapBox(std::boxed::Box<[T]>); 11 | 12 | impl From> for WrapBox { 13 | fn from(data: Vec) -> Self { 14 | WrapBox(data.into_boxed_slice()) 15 | } 16 | } 17 | 18 | impl Into> for WrapBox { 19 | fn into(self) -> Box<[T]> { 20 | self.0 21 | } 22 | } 23 | 24 | impl Default for WrapBox { 25 | fn default() -> Self { 26 | let v : std::vec::Vec = std::vec::Vec::new(); 27 | let b = v.into_boxed_slice(); 28 | return WrapBox::(b); 29 | } 30 | } 31 | 32 | impl super::SliceWrapper for WrapBox { 33 | fn slice(&self) -> & [T] { 34 | return &*self.0 35 | } 36 | } 37 | 38 | impl super::SliceWrapperMut for WrapBox { 39 | fn slice_mut(&mut self) -> &mut [T] { 40 | return &mut*self.0 41 | } 42 | } 43 | impl ops::Index for WrapBox { 44 | type Output = T; 45 | fn index(&self, index: usize) -> &T { 46 | &(*self.0)[index] 47 | } 48 | } 49 | 50 | impl ops::IndexMut for WrapBox { 51 | fn index_mut(&mut self, index: usize) -> &mut T { 52 | &mut (*self.0)[index] 53 | } 54 | } 55 | 56 | impl ops::Index> for WrapBox { 57 | type Output = [T]; 58 | fn index(&self, index: Range) -> &[T] { 59 | &(*self.0)[index] 60 | } 61 | } 62 | 63 | impl ops::IndexMut> for WrapBox { 64 | fn index_mut(&mut self, index: Range) -> &mut [T] { 65 | &mut (*self.0)[index] 66 | } 67 | } 68 | 69 | 70 | pub struct HeapAlloc{ 71 | pub default_value : T, 72 | } 73 | 74 | impl Default for HeapAlloc { 75 | fn default() -> Self { 76 | Self::new(T::default()) 77 | } 78 | } 79 | 80 | impl HeapAlloc { 81 | pub fn new(data : T) -> HeapAlloc { 82 | return HeapAlloc::{default_value : data}; 83 | } 84 | } 85 | 86 | impl super::Allocator for HeapAlloc { 87 | type AllocatedMemory = WrapBox; 88 | fn alloc_cell(self : &mut HeapAlloc, len : usize) -> WrapBox { 89 | 90 | let v : std::vec::Vec = vec![self.default_value.clone();len]; 91 | let b = v.into_boxed_slice(); 92 | return WrapBox::(b); 93 | } 94 | fn free_cell(self : &mut HeapAlloc, _data : WrapBox) { 95 | 96 | } 97 | } 98 | 99 | #[deprecated] 100 | pub type HeapAllocUninitialized = HeapAlloc; 101 | 102 | 103 | pub struct HeapPrealloc<'a, T : 'a> { 104 | freelist : std::boxed::Box<[&'a mut [T]]>, 105 | } 106 | define_stack_allocator_traits!(HeapPrealloc, heap); 107 | 108 | impl<'a, T : Clone+'a> HeapPrealloc<'a, T> { 109 | fn make_freelist(freelist_size : usize) -> std::boxed::Box<[&'a mut[T]]> { 110 | let mut retval = Vec::<&'a mut[T]>::with_capacity(freelist_size); 111 | for _i in 0..freelist_size { 112 | retval.push(&mut[]); 113 | } 114 | return retval.into_boxed_slice(); 115 | } 116 | pub fn new_allocator(freelist_size : usize, 117 | memory_pool : &'a mut Box<[T]>, 118 | initializer : fn(&mut[T])) -> super::StackAllocator<'a, T, HeapPrealloc<'a, T> > { 119 | let mut retval = super::StackAllocator:: > { 120 | nop : &mut [], 121 | system_resources : HeapPrealloc:: { 122 | freelist : Self::make_freelist(freelist_size), 123 | }, 124 | free_list_start : freelist_size, 125 | free_list_overflow_count : 0, 126 | initialize : initializer, 127 | }; 128 | retval.free_cell(super::AllocatedStackMemory::{mem:&mut*memory_pool}); 129 | return retval; 130 | } 131 | #[cfg(feature="unsafe")] 132 | pub unsafe fn new_uninitialized_memory_pool(len : usize) -> Box<[T]> { 133 | let mut v : std::vec::Vec = std::vec::Vec::with_capacity(len); 134 | v.set_len(len); 135 | return v.into_boxed_slice(); 136 | } 137 | } 138 | 139 | -------------------------------------------------------------------------------- /alloc-stdlib/src/bin/example.rs: -------------------------------------------------------------------------------- 1 | //#![feature(trace_macros)] 2 | extern crate alloc_stdlib; 3 | #[macro_use] 4 | extern crate alloc_no_stdlib; 5 | 6 | extern crate core; 7 | use core::ops; 8 | 9 | pub use alloc_stdlib::{HeapAlloc, StandardAlloc}; 10 | use alloc_stdlib::HeapPrealloc; 11 | mod tests; 12 | extern { 13 | fn calloc(n_elem : usize, el_size : usize) -> *mut u8; 14 | } 15 | extern { 16 | fn free(ptr : *mut u8); 17 | } 18 | 19 | 20 | //use alloc::AllocatedSlice; 21 | use alloc_no_stdlib::SliceWrapper; 22 | use alloc_no_stdlib::SliceWrapperMut; 23 | use alloc_no_stdlib::AllocatedStackMemory; 24 | use alloc_no_stdlib::Allocator; 25 | use alloc_no_stdlib::StackAllocator; 26 | 27 | use alloc_no_stdlib::bzero; 28 | declare_stack_allocator_struct!(CallocAllocatedFreelist4, 4, calloc); 29 | declare_stack_allocator_struct!(StackAllocatedFreelist16, 16, stack); 30 | 31 | fn show_heap_prealloc() { 32 | let mut zero_global_buffer = define_allocator_memory_pool!(4, u8, [0; 1024 * 1024 * 20], heap); 33 | 34 | let mut boxallocator = HeapPrealloc::::new_allocator(1024 * 1024, &mut zero_global_buffer, bzero); 35 | 36 | { 37 | let mut x = boxallocator.alloc_cell(9999); 38 | x.slice_mut()[0] = 3; 39 | let mut y = boxallocator.alloc_cell(4); 40 | y[0] = 5; 41 | boxallocator.free_cell(y); 42 | 43 | let mut three = boxallocator.alloc_cell(3); 44 | three[0] = 6; 45 | boxallocator.free_cell(three); 46 | 47 | let mut z = boxallocator.alloc_cell(4); 48 | z.slice_mut()[1] = 8; 49 | let mut reget_three = boxallocator.alloc_cell(4); 50 | reget_three.slice_mut()[1] = 9; 51 | //y.mem[0] = 6; // <-- this is an error (use after free) 52 | 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]); 53 | let mut _z = boxallocator.alloc_cell(1); 54 | } 55 | } 56 | 57 | fn main() { 58 | let mut global_buffer = unsafe {define_allocator_memory_pool!(4, u8, [0; 1024 * 1024 * 200], calloc)}; 59 | { 60 | let gbref = &mut global_buffer; 61 | { 62 | let mut ags = CallocAllocatedFreelist4::::new_allocator(gbref.data, bzero); 63 | 64 | { 65 | let mut x = ags.alloc_cell(9999); 66 | x.slice_mut()[0] = 4; 67 | let mut y = ags.alloc_cell(4); 68 | y[0] = 5; 69 | ags.free_cell(y); 70 | 71 | let mut three = ags.alloc_cell(3); 72 | three[0] = 6; 73 | ags.free_cell(three); 74 | 75 | let mut z = ags.alloc_cell(4); 76 | z.slice_mut()[1] = 8; 77 | let mut reget_three = ags.alloc_cell(4); 78 | reget_three.slice_mut()[1] = 9; 79 | //y.mem[0] = 6; // <-- this is an error (use after free) 80 | 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]); 81 | let mut _z = ags.alloc_cell(1); 82 | } 83 | } 84 | } 85 | 86 | 87 | let mut stack_global_buffer = define_allocator_memory_pool!(16, u8, [0; 1024 * 1024], stack); 88 | let mut stackallocator = StackAllocatedFreelist16::::new_allocator(&mut stack_global_buffer, bzero); 89 | { 90 | let mut x = stackallocator.alloc_cell(9999); 91 | x.slice_mut()[0] = 3; 92 | let mut y = stackallocator.alloc_cell(4); 93 | y[0] = 5; 94 | stackallocator.free_cell(y); 95 | 96 | let mut three = stackallocator.alloc_cell(3); 97 | three[0] = 6; 98 | stackallocator.free_cell(three); 99 | 100 | let mut z = stackallocator.alloc_cell(4); 101 | z.slice_mut()[1] = 8; 102 | let mut reget_three = stackallocator.alloc_cell(4); 103 | reget_three.slice_mut()[1] = 9; 104 | //y.mem[0] = 6; // <-- this is an error (use after free) 105 | 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]); 106 | let mut _z = stackallocator.alloc_cell(1); 107 | } 108 | 109 | let mut halloc = HeapAlloc::::default(); 110 | for _i in 1..10 { // heap test 111 | let mut x = halloc.alloc_cell(100000); 112 | x.slice_mut()[0] = 4; 113 | let mut y = halloc.alloc_cell(110000); 114 | y.slice_mut()[0] = 5; 115 | let mut z = halloc.alloc_cell(120000); 116 | z.slice_mut()[0] = 6; 117 | halloc.free_cell(y); 118 | println!("x[0] {:?} x[9] {:?} y[0] {:?} z[0] {:?}", 119 | x.slice()[0], x.slice()[9], -999, z.slice()[0]); 120 | } 121 | show_heap_prealloc(); 122 | } 123 | -------------------------------------------------------------------------------- /src/stack_allocator.rs: -------------------------------------------------------------------------------- 1 | extern crate core; 2 | use super::allocated_memory; 3 | use super::allocated_stack_memory::AllocatedStackMemory; 4 | use super::SliceWrapper; 5 | 6 | pub trait Allocator { 7 | type AllocatedMemory : allocated_memory::AllocatedSlice; 8 | fn alloc_cell(&mut self, len : usize) -> Self::AllocatedMemory; 9 | fn free_cell(&mut self, data : Self::AllocatedMemory); 10 | } 11 | 12 | 13 | pub struct StackAllocator<'a, 14 | T :'a, 15 | U : allocated_memory::AllocatedSlice<&'a mut [T]>> { 16 | pub nop : &'a mut [T], 17 | pub system_resources : U, 18 | pub free_list_start : usize, 19 | pub free_list_overflow_count : usize, 20 | pub initialize : fn(&mut[T]), 21 | } 22 | 23 | impl <'a, T : 'a, U : allocated_memory::AllocatedSlice<&'a mut[T]> > 24 | StackAllocator <'a, T, U> { 25 | fn clear_if_necessary(self : &Self, index : usize, data : AllocatedStackMemory<'a, T>) 26 | -> AllocatedStackMemory<'a, T> { 27 | if index + 1 != self.system_resources.slice().len() { 28 | let fnp = self.initialize; 29 | fnp(data.mem); 30 | } 31 | return data; 32 | } 33 | } 34 | impl<'a, T : 'a, U : allocated_memory::AllocatedSlice<&'a mut[T]> > 35 | Allocator for StackAllocator <'a, T, U> { 36 | type AllocatedMemory = AllocatedStackMemory<'a, T>; 37 | fn alloc_cell(self : &mut StackAllocator<'a, T, U>, 38 | len : usize) -> AllocatedStackMemory<'a, T> { 39 | if len == 0 { 40 | return AllocatedStackMemory::<'a, T>::default(); 41 | } 42 | let mut index : usize = self.free_list_start; 43 | let mut found : bool = false; 44 | for free_resource in self.system_resources.slice()[self.free_list_start..].iter() { 45 | if free_resource.len() >= len { 46 | found = true; 47 | break; 48 | } 49 | index += 1; 50 | } 51 | if !found { 52 | panic!("OOM"); 53 | } 54 | let available_slice = core::mem::replace(&mut self.system_resources.slice_mut()[index], 55 | &mut[]); 56 | if available_slice.len() == len 57 | || (available_slice.len() < len + 32 58 | && index + 1 != self.system_resources.slice().len()) { 59 | // we don't want really small wasted slices 60 | // we must assign free_list_start 61 | if index != self.free_list_start { 62 | assert!(index > self.free_list_start); 63 | let farthest_free_list = core::mem::replace( 64 | &mut self.system_resources.slice_mut()[self.free_list_start], 65 | &mut []); 66 | let _ = core::mem::replace(&mut self.system_resources.slice_mut()[index], 67 | farthest_free_list); 68 | } 69 | self.free_list_start += 1; 70 | return self.clear_if_necessary(index, 71 | AllocatedStackMemory::<'a, T>{mem:available_slice}); 72 | } else { // the memory allocated was not the entire range of items. Split and move on 73 | let (retval, return_to_sender) = available_slice.split_at_mut(len); 74 | let _ = core::mem::replace(&mut self.system_resources.slice_mut()[index], return_to_sender); 75 | return self.clear_if_necessary(index, AllocatedStackMemory::<'a, T>{mem:retval}); 76 | } 77 | } 78 | fn free_cell(self : &mut StackAllocator<'a, T, U>, 79 | val : AllocatedStackMemory<'a, T>) { 80 | if val.slice().len() == 0 { 81 | return; 82 | } 83 | if self.free_list_start > 0 { 84 | self.free_list_start -=1; 85 | let _ = core::mem::replace(&mut self.system_resources.slice_mut()[self.free_list_start], 86 | val.mem); 87 | 88 | } else { 89 | for _i in 0..3 { 90 | self.free_list_overflow_count += 1; 91 | self.free_list_overflow_count %= self.system_resources.slice().len(); 92 | if self.system_resources.slice()[self.free_list_overflow_count].len() < val.mem.len() { 93 | let _ = core::mem::replace(&mut self.system_resources.slice_mut()[self.free_list_overflow_count], 94 | val.mem); 95 | return; 96 | } 97 | } 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/allocated_memory/index_macro.rs: -------------------------------------------------------------------------------- 1 | #[macro_export] 2 | macro_rules! define_index_ops_mut { 3 | ($T:ident, $MemoryType:ty) => { 4 | impl<$T> ::core::ops::Index for $MemoryType 5 | { 6 | type Output = T; 7 | 8 | #[inline] 9 | fn index(&self, index: usize) -> &Self::Output { 10 | ::core::ops::Index::index(&**self, index) 11 | } 12 | } 13 | 14 | impl<$T> ::core::ops::IndexMut for $MemoryType 15 | { 16 | #[inline] 17 | fn index_mut(&mut self, index: usize) -> &mut Self::Output { 18 | ::core::ops::IndexMut::index_mut(&mut **self, index) 19 | } 20 | } 21 | 22 | 23 | impl<$T> ::core::ops::Index<::core::ops::Range> for $MemoryType 24 | { 25 | type Output = [T]; 26 | #[inline] 27 | fn index(&self, index: ::core::ops::Range) -> &Self::Output { 28 | ::core::ops::Index::index(&**self, index) 29 | } 30 | } 31 | 32 | impl<$T> ::core::ops::IndexMut<::core::ops::Range> for $MemoryType 33 | { 34 | #[inline] 35 | fn index_mut(&mut self, index: ::core::ops::Range) -> &mut Self::Output { 36 | ::core::ops::IndexMut::index_mut(&mut **self, index) 37 | } 38 | } 39 | 40 | 41 | impl<$T> ::core::ops::Deref for $MemoryType { 42 | type Target = [T]; 43 | 44 | fn deref(&self) -> &[T] { 45 | self.slice() 46 | } 47 | } 48 | 49 | impl ::core::ops::DerefMut for $MemoryType { 50 | fn deref_mut(&mut self) -> &mut [T] { 51 | self.slice_mut() 52 | } 53 | } 54 | }; 55 | ($T0: ident, $T:ident, $MemoryType:ty) => { 56 | impl<'a, $T> ::core::ops::Index for $MemoryType 57 | { 58 | type Output = T; 59 | 60 | #[inline] 61 | fn index(&self, index: usize) -> &Self::Output { 62 | ::core::ops::Index::index(&**self, index) 63 | } 64 | } 65 | 66 | impl<'a, $T> ::core::ops::IndexMut for $MemoryType 67 | { 68 | #[inline] 69 | fn index_mut(&mut self, index: usize) -> &mut Self::Output { 70 | ::core::ops::IndexMut::index_mut(&mut **self, index) 71 | } 72 | } 73 | 74 | 75 | impl<'a, $T> ::core::ops::Index<::core::ops::Range> for $MemoryType 76 | { 77 | type Output = [T]; 78 | 79 | #[inline] 80 | fn index(&self, index: ::core::ops::Range) -> &Self::Output { 81 | ::core::ops::Index::index(&**self, index) 82 | } 83 | } 84 | 85 | 86 | impl<'a, $T> ::core::ops::IndexMut<::core::ops::Range> for $MemoryType 87 | { 88 | #[inline] 89 | fn index_mut(&mut self, index: ::core::ops::Range) -> &mut Self::Output { 90 | ::core::ops::IndexMut::index_mut(&mut **self, index) 91 | } 92 | } 93 | 94 | 95 | impl<'a, $T> ::core::ops::Deref for $MemoryType { 96 | type Target = [T]; 97 | 98 | fn deref(&self) -> &[T] { 99 | self.slice() 100 | } 101 | } 102 | impl<'a, $T> ::core::ops::DerefMut for $MemoryType { 103 | fn deref_mut(&mut self) -> &mut [T] { 104 | self.slice_mut() 105 | } 106 | } 107 | } 108 | } 109 | #[macro_export] 110 | macro_rules! define_index_ops { 111 | ($T:ident, $MemoryType:ty) => { 112 | impl<$T> ::core::ops::Index for $MemoryType 113 | { 114 | type Output = T; 115 | 116 | #[inline] 117 | fn index(&self, index: usize) -> &Self::Output { 118 | ::core::ops::Index::index(&**self, index) 119 | } 120 | } 121 | 122 | 123 | impl<$T> ::core::ops::Index<::core::ops::Range> for $MemoryType 124 | { 125 | type Output = [T]; 126 | 127 | #[inline] 128 | fn index(&self, index: ::core::ops::Range) -> &Self::Output { 129 | ::core::ops::Index::index(&**self, index) 130 | } 131 | } 132 | 133 | impl<$T> ::core::ops::Deref for $MemoryType { 134 | type Target = [T]; 135 | 136 | fn deref(&self) -> &[T] { 137 | self.slice() 138 | } 139 | } 140 | 141 | }; 142 | ($T0: tt, $T:ident, $MemoryType:ty) => { 143 | impl<'a, $T> ::core::ops::Index for $MemoryType 144 | { 145 | type Output = T; 146 | 147 | #[inline] 148 | fn index(&self, index: usize) -> &Self::Output { 149 | ::core::ops::Index::index(&**self, index) 150 | } 151 | } 152 | 153 | impl<'a, $T> ::core::ops::Index<::core::ops::Range> for $MemoryType 154 | { 155 | type Output = [T]; 156 | 157 | #[inline] 158 | fn index(&self, index: ::core::ops::Range) -> &Self::Output { 159 | ::core::ops::Index::index(&**self, index) 160 | } 161 | } 162 | 163 | 164 | impl<'a, $T> ::core::ops::Deref for $MemoryType { 165 | type Target = [T]; 166 | 167 | fn deref(&self) -> &[T] { 168 | self.slice() 169 | } 170 | } 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /alloc-stdlib/README.md: -------------------------------------------------------------------------------- 1 | # Framework for allocating memory in #![no_std] modules. 2 | 3 | [![crates.io](http://meritbadge.herokuapp.com/alloc-no-stdlib)](https://crates.io/crates/alloc-no-stdlib) 4 | [![Build Status](https://travis-ci.org/dropbox/rust-alloc-no-stdlib.svg?branch=master)](https://travis-ci.org/dropbox/rust-alloc-no-stdlib) 5 | 6 | 7 | ## Requirements 8 | * Rust 1.6 9 | 10 | ## Documentation 11 | Currently there is no standard way to allocate memory from within a module that is no_std. 12 | This provides a mechanism to allocate memory using the stdlib-independent 13 | memory allocation system described by rust-alloc-no-stdlib 14 | describe a memory allocation that can be satisfied entirely on 15 | the stack, by unsafely linking to calloc, or by unsafely referencing a mutable global variable. 16 | This library currently will leak memory if free_cell isn't specifically invoked on memory. 17 | 18 | However, if linked by a library that actually can depend on the stdlib then that library 19 | can simply pass in a few allocators and use the standard Box allocation and will free automatically. 20 | 21 | This library should also make it possible to entirely jail a rust application that needs dynamic 22 | allocations by preallocating a maximum limit of data upfront using calloc and 23 | using seccomp to disallow future syscalls. 24 | 25 | ## Usage 26 | 27 | There are 3 modes for allocating memory using the stdlib, each with advantages and disadvantages 28 | 29 | 30 | ### On the heap 31 | This uses the standard Box facilities to allocate memory and assumeds a default constructor 32 | for the given type 33 | 34 | ```rust 35 | let mut halloc = StandardAlloc::new(0); 36 | for _i in 1..10 { // heap test 37 | let mut x = >::alloc_cell(&mut halloc, 100000) 38 | x[0] = 4; 39 | let mut y = >::alloc_cell(&mut halloc, 100000) 40 | y[0] = 5; 41 | let mut z = >::alloc_cell(&mut halloc, 100000) 42 | z[0] = 6; 43 | assert_eq!(y[0], 5); 44 | halloc.free_cell(y); 45 | assert_eq!(x[0], 4); 46 | assert_eq!(x[9], 0); 47 | assert_eq!(z[0], 6); 48 | } 49 | ``` 50 | 51 | ### On the heap 52 | This uses the standard Box facilities to allocate memory but assuming a default user-provided value 53 | 54 | ```rust 55 | let mut halloc = HeapAlloc::::new(8); 56 | for _i in 1..10 { // heap test 57 | let mut x = halloc.alloc_cell(100000); 58 | x[0] = 4; 59 | let mut y = halloc.alloc_cell(110000); 60 | y[0] = 5; 61 | let mut z = halloc.alloc_cell(120000); 62 | z[0] = 6; 63 | assert_eq!(y[0], 5); 64 | halloc.free_cell(y); 65 | assert_eq!(x[0], 4); 66 | assert_eq!(x[9], 8); 67 | assert_eq!(z[0], 6); 68 | } 69 | ``` 70 | 71 | 72 | ### On the heap, but uninitialized 73 | This does allocate data every time it is requested, but it does not allocate the 74 | memory, so naturally it is unsafe. The caller must initialize the memory properly 75 | ```rust 76 | let mut halloc = unsafe{HeapAllocUninitialized::::new()}; 77 | { // heap test 78 | let mut x = halloc.alloc_cell(100000); 79 | x[0] = 4; 80 | let mut y = halloc.alloc_cell(110000); 81 | y[0] = 5; 82 | let mut z = halloc.alloc_cell(120000); 83 | z[0] = 6; 84 | assert_eq!(y[0], 5); 85 | halloc.free_cell(y); 86 | assert_eq!(x[0], 4); 87 | assert_eq!(x[9], 0); 88 | assert_eq!(z[0], 6); 89 | ... 90 | } 91 | ``` 92 | 93 | 94 | ### On the heap in a single pool allocation 95 | This does a single big allocation on the heap, after which no further usage of the stdlib 96 | will happen. This can be useful for a jailed application that wishes to restrict syscalls 97 | at this point 98 | 99 | ```rust 100 | use alloc_no_stdlib::HeapPrealloc; 101 | ... 102 | let mut heap_global_buffer = define_allocator_memory_pool!(4096, u8, [0; 6 * 1024 * 1024], heap); 103 | let mut ags = HeapPrealloc::::new_allocator(4096, &mut heap_global_buffer, uninitialized); 104 | { 105 | let mut x = ags.alloc_cell(9999); 106 | x.slice_mut()[0] = 4; 107 | let mut y = ags.alloc_cell(4); 108 | y[0] = 5; 109 | ags.free_cell(y); 110 | 111 | //y.mem[0] = 6; // <-- this is an error (use after free) 112 | } 113 | ``` 114 | 115 | 116 | 117 | ### On the heap, uninitialized 118 | This does a single big allocation on the heap, after which no further usage of the stdlib 119 | will happen. This can be useful for a jailed application that wishes to restrict syscalls 120 | at this point. This option keep does not set the memory to a valid value, so it is 121 | necessarily marked unsafe 122 | 123 | ```rust 124 | use alloc_no_stdlib::HeapPrealloc; 125 | ... 126 | let mut heap_global_buffer = unsafe{HeapPrealloc::::new_uninitialized_memory_pool(6 * 1024 * 1024)}; 127 | let mut ags = HeapPrealloc::::new_allocator(4096, &mut heap_global_buffer, uninitialized); 128 | { 129 | let mut x = ags.alloc_cell(9999); 130 | x.slice_mut()[0] = 4; 131 | let mut y = ags.alloc_cell(4); 132 | y[0] = 5; 133 | ags.free_cell(y); 134 | 135 | //y.mem[0] = 6; // <-- this is an error (use after free) 136 | } 137 | ``` 138 | 139 | ### With calloc 140 | This is the most efficient way to get a zero'd dynamically sized buffer without the stdlib 141 | It does invoke the C calloc function and hence must invoke unsafe code. 142 | In this version, the number of cells are fixed to the parameter specified in the struct definition 143 | (4096 in this example) 144 | 145 | ```rust 146 | extern { 147 | fn calloc(n_elem : usize, el_size : usize) -> *mut u8; 148 | fn malloc(len : usize) -> *mut u8; 149 | fn free(item : *mut u8); 150 | } 151 | 152 | declare_stack_allocator_struct!(CallocAllocatedFreelist4096, 4096, calloc); 153 | ... 154 | 155 | // the buffer is defined with 200 megs of zero'd memory from calloc 156 | let mut calloc_global_buffer = unsafe {define_allocator_memory_pool!(4096, u8, [0; 200 * 1024 * 1024], calloc)}; 157 | // and assigned to a new_allocator 158 | let mut ags = CallocAllocatedFreelist4096::::new_allocator(&mut calloc_global_buffer.data, bzero); 159 | { 160 | let mut x = ags.alloc_cell(9999); 161 | x.slice_mut()[0] = 4; 162 | let mut y = ags.alloc_cell(4); 163 | y[0] = 5; 164 | ags.free_cell(y); 165 | //y.mem[0] = 6; // <-- this is an error (use after free) 166 | } 167 | ``` 168 | 169 | ### With a static, mutable buffer 170 | If a single buffer of data is needed for the entire span of the application 171 | Then the simplest way to do so without a zero operation on 172 | the memory and without using the stdlib is to simply have a global allocated 173 | structure. Accessing mutable static variables requires unsafe code; however, 174 | so this code will invoke an unsafe block. 175 | 176 | 177 | Make sure to only reference global_buffer in a single place, at a single time in the code 178 | If it is used from two places or at different times, undefined behavior may result, 179 | since multiple allocators may get access to global_buffer. 180 | 181 | 182 | ```rust 183 | declare_stack_allocator_struct!(GlobalAllocatedFreelist, 16, global); 184 | define_allocator_memory_pool!(16, u8, [0; 1024 * 1024 * 100], global, global_buffer); 185 | 186 | ... 187 | // this references a global buffer 188 | let mut ags = GlobalAllocatedFreelist::::new_allocator(bzero); 189 | unsafe { 190 | bind_global_buffers_to_allocator!(ags, global_buffer, u8); 191 | } 192 | { 193 | let mut x = ags.alloc_cell(9999); 194 | x.slice_mut()[0] = 4; 195 | let mut y = ags.alloc_cell(4); 196 | y[0] = 5; 197 | ags.free_cell(y); 198 | 199 | //y.mem[0] = 6; // <-- this is an error (use after free) 200 | } 201 | ``` 202 | 203 | 204 | ## Contributors 205 | - Daniel Reiter Horn 206 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Framework for allocating memory in #![no_std] modules. 2 | 3 | [![crates.io](http://meritbadge.herokuapp.com/alloc-no-stdlib)](https://crates.io/crates/alloc-no-stdlib) 4 | [![Build Status](https://travis-ci.org/dropbox/rust-alloc-no-stdlib.svg?branch=master)](https://travis-ci.org/dropbox/rust-alloc-no-stdlib) 5 | 6 | 7 | ## Requirements 8 | * Rust 1.6 9 | 10 | ## Documentation 11 | Currently there is no standard way to allocate memory from within a module that is no_std. 12 | This provides a mechanism to describe a memory allocation that can be satisfied entirely on 13 | the stack, by unsafely linking to calloc, or by unsafely referencing a mutable global variable. 14 | This library currently will leak memory if free_cell isn't specifically invoked on memory. 15 | 16 | However, if linked by a library that actually can depend on the stdlib then that library 17 | can simply pass in a few allocators and use the standard Box allocation and will free automatically. 18 | 19 | This library should also make it possible to entirely jail a rust application that needs dynamic 20 | allocations by preallocating a maximum limit of data upfront using calloc and 21 | using seccomp to disallow future syscalls. 22 | 23 | ## Usage 24 | 25 | There are 3 modes for allocating memory, each with advantages and disadvantages 26 | 27 | ### On the stack 28 | This is possible without the stdlib at all 29 | However, this eats into the natural ulimit on the stack depth and generally 30 | limits the program to only a few megs of dynamically allocated data 31 | 32 | Example: 33 | 34 | ```rust 35 | // First define a struct to hold all the array on the stack. 36 | declare_stack_allocator_struct!(StackAllocatedFreelist4, 4, stack); 37 | // since generics cannot be used, the actual struct to hold the memory must be defined with a macro 38 | ... 39 | 40 | // in the code where the memory must be used, first the array needs to be readied 41 | let mut stack_buffer = define_allocator_memory_pool!(4, u8, [0; 65536], stack); 42 | // then an allocator needs to be made and pointed to the stack_buffer on the stack 43 | // the final argument tells the system if free'd data should be zero'd before being 44 | // reused by a subsequent call to alloc_cell 45 | let mut ags = StackAllocatedFreelist4::::new_allocator(&mut stack_buffer, bzero); 46 | { 47 | // now we can get memory dynamically 48 | let mut x = ags.alloc_cell(9999); 49 | x.slice_mut()[0] = 4; 50 | // get more memory 51 | let mut y = ags.alloc_cell(4); 52 | y[0] = 5; 53 | // and free it, consuming the buffer 54 | ags.free_cell(y); 55 | 56 | //y.mem[0] = 6; // <-- this is an error: won't compile (use after free) 57 | assert_eq!(x[0], 4); 58 | ``` 59 | 60 | ### On the heap 61 | This uses the standard Box facilities to allocate memory 62 | 63 | ```rust 64 | let mut halloc = HeapAlloc::::new(0); 65 | for _i in 1..10 { // heap test 66 | let mut x = halloc.alloc_cell(100000); 67 | x[0] = 4; 68 | let mut y = halloc.alloc_cell(110000); 69 | y[0] = 5; 70 | let mut z = halloc.alloc_cell(120000); 71 | z[0] = 6; 72 | assert_eq!(y[0], 5); 73 | halloc.free_cell(y); 74 | assert_eq!(x[0], 4); 75 | assert_eq!(x[9], 0); 76 | assert_eq!(z[0], 6); 77 | } 78 | ``` 79 | 80 | ### On the heap, but uninitialized 81 | This does allocate data every time it is requested, but it does not allocate the 82 | memory, so naturally it is unsafe. The caller must initialize the memory properly 83 | ```rust 84 | let mut halloc = unsafe{HeapAllocUninitialized::::new()}; 85 | { // heap test 86 | let mut x = halloc.alloc_cell(100000); 87 | x[0] = 4; 88 | let mut y = halloc.alloc_cell(110000); 89 | y[0] = 5; 90 | let mut z = halloc.alloc_cell(120000); 91 | z[0] = 6; 92 | assert_eq!(y[0], 5); 93 | halloc.free_cell(y); 94 | assert_eq!(x[0], 4); 95 | assert_eq!(x[9], 0); 96 | assert_eq!(z[0], 6); 97 | ... 98 | } 99 | ``` 100 | 101 | 102 | ### On the heap in a single pool allocation 103 | This does a single big allocation on the heap, after which no further usage of the stdlib 104 | will happen. This can be useful for a jailed application that wishes to restrict syscalls 105 | at this point 106 | 107 | ```rust 108 | use alloc_no_stdlib::HeapPrealloc; 109 | ... 110 | let mut heap_global_buffer = define_allocator_memory_pool!(4096, u8, [0; 6 * 1024 * 1024], heap); 111 | let mut ags = HeapPrealloc::::new_allocator(4096, &mut heap_global_buffer, uninitialized); 112 | { 113 | let mut x = ags.alloc_cell(9999); 114 | x.slice_mut()[0] = 4; 115 | let mut y = ags.alloc_cell(4); 116 | y[0] = 5; 117 | ags.free_cell(y); 118 | 119 | //y.mem[0] = 6; // <-- this is an error (use after free) 120 | } 121 | ``` 122 | 123 | 124 | 125 | ### On the heap, uninitialized 126 | This does a single big allocation on the heap, after which no further usage of the stdlib 127 | will happen. This can be useful for a jailed application that wishes to restrict syscalls 128 | at this point. This option keep does not set the memory to a valid value, so it is 129 | necessarily marked unsafe 130 | 131 | ```rust 132 | use alloc_no_stdlib::HeapPrealloc; 133 | ... 134 | let mut heap_global_buffer = unsafe{HeapPrealloc::::new_uninitialized_memory_pool(6 * 1024 * 1024)}; 135 | let mut ags = HeapPrealloc::::new_allocator(4096, &mut heap_global_buffer, uninitialized); 136 | { 137 | let mut x = ags.alloc_cell(9999); 138 | x.slice_mut()[0] = 4; 139 | let mut y = ags.alloc_cell(4); 140 | y[0] = 5; 141 | ags.free_cell(y); 142 | 143 | //y.mem[0] = 6; // <-- this is an error (use after free) 144 | } 145 | ``` 146 | 147 | ### With calloc 148 | This is the most efficient way to get a zero'd dynamically sized buffer without the stdlib 149 | It does invoke the C calloc function and hence must invoke unsafe code. 150 | In this version, the number of cells are fixed to the parameter specified in the struct definition 151 | (4096 in this example) 152 | 153 | ```rust 154 | extern { 155 | fn calloc(n_elem : usize, el_size : usize) -> *mut u8; 156 | fn malloc(len : usize) -> *mut u8; 157 | fn free(item : *mut u8); 158 | } 159 | 160 | declare_stack_allocator_struct!(CallocAllocatedFreelist4096, 4096, calloc); 161 | ... 162 | 163 | // the buffer is defined with 200 megs of zero'd memory from calloc 164 | let mut calloc_global_buffer = unsafe {define_allocator_memory_pool!(4096, u8, [0; 200 * 1024 * 1024], calloc)}; 165 | // and assigned to a new_allocator 166 | let mut ags = CallocAllocatedFreelist4096::::new_allocator(&mut calloc_global_buffer.data, bzero); 167 | { 168 | let mut x = ags.alloc_cell(9999); 169 | x.slice_mut()[0] = 4; 170 | let mut y = ags.alloc_cell(4); 171 | y[0] = 5; 172 | ags.free_cell(y); 173 | //y.mem[0] = 6; // <-- this is an error (use after free) 174 | } 175 | ``` 176 | 177 | ### With a static, mutable buffer 178 | If a single buffer of data is needed for the entire span of the application 179 | Then the simplest way to do so without a zero operation on 180 | the memory and without using the stdlib is to simply have a global allocated 181 | structure. Accessing mutable static variables requires unsafe code; however, 182 | so this code will invoke an unsafe block. 183 | 184 | 185 | Make sure to only reference global_buffer in a single place, at a single time in the code 186 | If it is used from two places or at different times, undefined behavior may result, 187 | since multiple allocators may get access to global_buffer. 188 | 189 | 190 | ```rust 191 | declare_stack_allocator_struct!(GlobalAllocatedFreelist, 16, global); 192 | define_allocator_memory_pool!(16, u8, [0; 1024 * 1024 * 100], global, global_buffer); 193 | 194 | ... 195 | // this references a global buffer 196 | let mut ags = GlobalAllocatedFreelist::::new_allocator(bzero); 197 | unsafe { 198 | bind_global_buffers_to_allocator!(ags, global_buffer, u8); 199 | } 200 | { 201 | let mut x = ags.alloc_cell(9999); 202 | x.slice_mut()[0] = 4; 203 | let mut y = ags.alloc_cell(4); 204 | y[0] = 5; 205 | ags.free_cell(y); 206 | 207 | //y.mem[0] = 6; // <-- this is an error (use after free) 208 | } 209 | ``` 210 | 211 | 212 | ## Contributors 213 | - Daniel Reiter Horn 214 | -------------------------------------------------------------------------------- /src/init.rs: -------------------------------------------------------------------------------- 1 | #[macro_export] 2 | macro_rules! static_array { 3 | (@accum (0, $($_ignored:expr),*) -> ($($body:tt)*)) 4 | => {static_array!(@as_expr [$($body)*])}; 5 | (@accum (1, $($expr:expr),*) -> ($($body:tt)*)) 6 | => {static_array!(@accum (0, $($expr),*) -> ($($body)* $($expr,)*))}; 7 | (@accum (2, $($expr:expr),*) -> ($($body:tt)*)) 8 | => {static_array!(@accum (0, $($expr),*) -> ($($body)* $($expr,)* $($expr,)*))}; 9 | (@accum (4, $($expr:expr),*) -> ($($body:tt)*)) 10 | => {static_array!(@accum (2, $($expr,)* $($expr),*) -> ($($body)*))}; 11 | (@accum (8, $($expr:expr),*) -> ($($body:tt)*)) 12 | => {static_array!(@accum (4, $($expr,)* $($expr),*) -> ($($body)*))}; 13 | (@accum (16, $($expr:expr),*) -> ($($body:tt)*)) 14 | => {static_array!(@accum (8, $($expr,)* $($expr),*) -> ($($body)*))}; 15 | (@accum (32, $($expr:expr),*) -> ($($body:tt)*)) 16 | => {static_array!(@accum (16, $($expr,)* $($expr),*) -> ($($body)*))}; 17 | (@accum (64, $($expr:expr),*) -> ($($body:tt)*)) 18 | => {static_array!(@accum (32, $($expr,)* $($expr),*) -> ($($body)*))}; 19 | (@accum (128, $($expr:expr),*) -> ($($body:tt)*)) 20 | => {static_array!(@accum (64, $($expr,)* $($expr),*) -> ($($body)*))}; 21 | (@accum (256, $($expr:expr),*) -> ($($body:tt)*)) 22 | => {static_array!(@accum (128, $($expr,)* $($expr),*) -> ($($body)*))}; 23 | (@accum (512, $($expr:expr),*) -> ($($body:tt)*)) 24 | => {static_array!(@accum (256, $($expr,)* $($expr),*) -> ($($body)*))}; 25 | (@accum (1024, $($expr:expr),*) -> ($($body:tt)*)) 26 | => {static_array!(@accum (512, $($expr,)* $($expr),*) -> ($($body)*))}; 27 | (@accum (2048, $($expr:expr),*) -> ($($body:tt)*)) 28 | => {static_array!(@accum (1024, $($expr,)* $($expr),*) -> ($($body)*))}; 29 | (@accum (4096, $($expr:expr),*) -> ($($body:tt)*)) 30 | => {static_array!(@accum (2048, $($expr,)* $($expr),*) -> ($($body)*))}; 31 | (@accum (8192, $($expr:expr),*) -> ($($body:tt)*)) 32 | => {static_array!(@accum (4096, $($expr,)* $($expr),*) -> ($($body)*))}; 33 | 34 | (@as_expr $expr:expr) => {$expr}; 35 | 36 | ($expr:expr; $n:tt) => { static_array!(@accum ($n, $expr) -> ()) }; 37 | } 38 | 39 | 40 | #[macro_export] 41 | macro_rules! define_stack_allocator_traits( 42 | ($name : ident, global) => { 43 | impl<'a, T: 'a> Default for $name<'a, T> { 44 | fn default() -> Self { 45 | return $name::<'a, T>{freelist : &mut[],}; 46 | } 47 | } 48 | define_stack_allocator_traits!($name, generic); 49 | }; 50 | ($name : ident, $freelist_size : tt, stack) => { 51 | impl<'a, T: 'a> Default for $name<'a, T> { 52 | fn default() -> Self { 53 | return $name::<'a, T>{freelist : static_array!(&mut[]; $freelist_size)}; 54 | } 55 | } 56 | define_stack_allocator_traits!($name, generic); 57 | }; 58 | ($name : ident, heap) => { 59 | impl<'a, T: 'a> Default for $name<'a, T> { 60 | fn default() -> Self { 61 | let v : Vec<&mut [T]> = Vec::new(); 62 | let b = v.into_boxed_slice(); 63 | return $name::<'a, T>{freelist : b}; 64 | } 65 | } 66 | define_stack_allocator_traits!($name, generic); 67 | }; 68 | ($name : ident, $freelist_size : tt, malloc) => { 69 | define_stack_allocator_traits!($name, calloc); 70 | }; 71 | ($name : ident, $freelist_size : tt, calloc) => { 72 | 73 | impl<'a, T: 'a> Default for $name<'a, T> { 74 | fn default() -> Self { 75 | return $name::<'a, T>{freelist : static_array!(&mut[]; $freelist_size)}; 76 | } 77 | } 78 | define_stack_allocator_traits!($name, generic); 79 | }; 80 | ($name : ident, generic) => { 81 | impl<'a, T: 'a> SliceWrapper<&'a mut[T]> for $name<'a, T> { 82 | fn slice(& self) -> & [&'a mut[T]] { 83 | return & self.freelist; 84 | } 85 | } 86 | impl<'a, T: 'a> SliceWrapperMut<&'a mut [T]> for $name<'a, T> { 87 | fn slice_mut(& mut self) ->&mut [&'a mut [T]] { 88 | return &mut self.freelist; 89 | } 90 | } 91 | impl<'a, T: 'a> ops::Index for $name<'a, T> { 92 | type Output = [T]; 93 | fn index<'b> (&'b self, _index : usize) -> &'b [T] { 94 | return &self.freelist[_index]; 95 | } 96 | } 97 | 98 | impl<'a, T: 'a> ops::IndexMut for $name<'a, T> { 99 | fn index_mut<'b>(&'b mut self, _index : usize) -> &'b mut [T] { 100 | return &mut self.freelist[_index]; 101 | } 102 | } 103 | }; 104 | ); 105 | 106 | #[macro_export] 107 | macro_rules! declare_stack_allocator_struct( 108 | (@as_expr $expr : expr) => {$expr}; 109 | (@new_method $name : ident, $freelist_size : tt) => { 110 | impl<'a, T: 'a> $name<'a, T> { 111 | fn new_allocator(global_buffer : &'a mut [T], 112 | initializer : fn(&mut[T])) -> StackAllocator<'a, T, $name<'a, T> > { 113 | let mut retval = StackAllocator:: > { 114 | nop : &mut [], 115 | system_resources : $name::::default(), 116 | free_list_start : declare_stack_allocator_struct!(@as_expr $freelist_size), 117 | free_list_overflow_count : 0, 118 | initialize : initializer, 119 | }; 120 | retval.free_cell(AllocatedStackMemory::{mem:global_buffer}); 121 | return retval; 122 | } 123 | } 124 | }; 125 | 126 | (@new_calloc_method $name : ident, $freelist_size : tt) => { 127 | impl<'a, T: 'a> $name<'a, T> { 128 | fn new_allocator(mut global_buffer : &'a mut [T], 129 | initializer : fn(&mut[T])) -> StackAllocator<'a, T, $name<'a, T> > { 130 | let mut retval = StackAllocator:: > { 131 | nop : &mut [], 132 | system_resources : $name::::default(), 133 | free_list_start : declare_stack_allocator_struct!(@as_expr $freelist_size), 134 | free_list_overflow_count : 0, 135 | initialize : initializer, 136 | }; 137 | retval.free_cell(AllocatedStackMemory::{mem:core::mem::replace(&mut global_buffer, &mut[])}); 138 | return retval; 139 | } 140 | } 141 | }; 142 | ($name :ident, $freelist_size : tt, malloc) => { 143 | declare_stack_allocator_struct!($name, $freelist_size, calloc); 144 | }; 145 | ($name :ident, $freelist_size : tt, calloc) => { 146 | struct $name<'a, T : 'a> { 147 | freelist : [&'a mut [T]; declare_stack_allocator_struct!(@as_expr $freelist_size)], 148 | } 149 | define_stack_allocator_traits!($name, 150 | $freelist_size, 151 | calloc); 152 | declare_stack_allocator_struct!( @new_calloc_method $name, $freelist_size); 153 | }; 154 | ($name :ident, $freelist_size : tt, stack) => { 155 | struct $name<'a, T : 'a> { 156 | freelist : [&'a mut [T];declare_stack_allocator_struct!(@as_expr $freelist_size)], 157 | // can't borrow here: make it on stack-- heap : core::cell::RefCell<[T; $heap_size]> 158 | } 159 | define_stack_allocator_traits!($name, 160 | $freelist_size, 161 | stack); 162 | declare_stack_allocator_struct!( @new_method $name, $freelist_size); 163 | }; 164 | ($name :ident, $freelist_size : expr, global) => { 165 | struct $name <'a, T: 'a> {freelist : &'a mut [&'a mut [T]]} 166 | define_stack_allocator_traits!($name, global); 167 | impl<'a, T: 'a> $name<'a, T> { 168 | fn new_allocator(initializer : fn (&mut[T])) -> StackAllocator<'a, T, $name<'a, T> > { 169 | return StackAllocator:: > { 170 | nop : &mut [], 171 | system_resources : $name::::default(), 172 | free_list_start : 0, 173 | free_list_overflow_count : 0, 174 | initialize : initializer, 175 | }; 176 | } 177 | } 178 | }; 179 | ); 180 | #[macro_export] 181 | macro_rules! bind_global_buffers_to_allocator( 182 | ($allocator : expr, $buffer : ident, $T : ty) => { 183 | $allocator.free_list_start = $buffer::FREELIST.len(); 184 | $allocator.system_resources.freelist = &mut $buffer::FREELIST; 185 | $allocator.free_cell(AllocatedStackMemory::<$T>{mem:&mut $buffer::HEAP}); 186 | }; 187 | ); 188 | 189 | #[macro_export] 190 | macro_rules! define_allocator_memory_pool( 191 | (@as_expr $expr:expr) => {$expr}; 192 | 193 | 194 | ($freelist_size : tt, $T : ty, [0; $heap_size : expr], calloc) => { 195 | alloc_no_stdlib::CallocBackingStore::<$T>::new($heap_size, alloc_no_stdlib::AllocatorC::Calloc(calloc), free, true); 196 | }; 197 | ($freelist_size : tt, $T : ty, [0; $heap_size : expr], calloc_no_free) => { 198 | alloc_no_stdlib::CallocBackingStore::<$T>::new($heap_size, alloc_no_stdlib::AllocatorC::Calloc(calloc), free, false); 199 | }; 200 | ($freelist_size : tt, $T : ty, [0; $heap_size : expr], malloc) => { 201 | alloc_no_stdlib::CallocBackingStore::<$T>::new($heap_size, alloc_no_stdlib::AllocatorC::Malloc(malloc), free, true); 202 | }; 203 | ($freelist_size : tt, $T : ty, [0; $heap_size : expr], malloc_no_free) => { 204 | alloc_no_stdlib::CallocBackingStore::<$T>::new($heap_size, alloc_no_stdlib::AllocatorC::Malloc(malloc), free, false); 205 | }; 206 | ($freelist_size : tt, $T : ty, [$default_value : expr; $heap_size : expr], heap) => { 207 | (vec![$default_value; $heap_size]).into_boxed_slice(); 208 | }; 209 | ($freelist_size : tt, $T : ty, [$default_value : expr; $heap_size : expr], stack) => { 210 | [$default_value; $heap_size]; 211 | }; 212 | ($freelist_size : tt, $T : ty, [$default_value : expr; $heap_size : expr], global, $name : ident) => { 213 | pub mod $name { 214 | pub static mut FREELIST : [&'static mut [$T]; 215 | define_allocator_memory_pool!(@as_expr $freelist_size)] 216 | = static_array!(&mut[]; $freelist_size); 217 | pub static mut HEAP : [$T; $heap_size] = [$default_value; $heap_size]; 218 | } 219 | }; 220 | 221 | ); 222 | 223 | 224 | -------------------------------------------------------------------------------- /tests/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused_imports)] 2 | #![allow(dead_code)] 3 | //#![feature(trace_macros)] 4 | 5 | #[cfg(test)] 6 | 7 | #[macro_use] 8 | extern crate alloc_no_stdlib; 9 | 10 | extern crate core; 11 | use core::ops; 12 | use alloc_no_stdlib::{Allocator, SliceWrapperMut, SliceWrapper, 13 | StackAllocator, AllocatedStackMemory, uninitialized, bzero}; 14 | 15 | declare_stack_allocator_struct!(CallocAllocatedFreelist4096, 4096, calloc); 16 | declare_stack_allocator_struct!(StackAllocatedFreelist4, 4, stack); 17 | declare_stack_allocator_struct!(StackAllocatedFreelist8, 8, stack); 18 | declare_stack_allocator_struct!(GlobalAllocatedFreelist, 16, global); 19 | //trace_macros!(true); 20 | 21 | define_allocator_memory_pool!(16, u8, [0; 1024 * 1024 * 100], global, global_buffer); 22 | define_allocator_memory_pool!(16, u8, [0; 1024 * 1024 * 100], global, global_buffer2); 23 | extern { 24 | fn calloc(n_elem : usize, el_size : usize) -> *mut u8; 25 | fn free(item : *mut u8); 26 | } 27 | #[test] 28 | fn uninitialized_stack_pool_test() { 29 | { 30 | let mut stack_global_buffer = define_allocator_memory_pool!(4, u8, [0; 65536], stack); 31 | let mut ags = StackAllocatedFreelist4::::new_allocator(&mut stack_global_buffer, uninitialized); 32 | { 33 | let mut x = ags.alloc_cell(9999); 34 | x.slice_mut()[0] = 4; 35 | let mut y = ags.alloc_cell(4); 36 | y[0] = 5; 37 | ags.free_cell(y); 38 | 39 | let mut three = ags.alloc_cell(3); 40 | three[0] = 6; 41 | ags.free_cell(three); 42 | 43 | let mut z = ags.alloc_cell(4); 44 | z.slice_mut()[1] = 8; 45 | let mut reget_three = ags.alloc_cell(4); 46 | reget_three.slice_mut()[1] = 9; 47 | //y.mem[0] = 6; // <-- this is an error (use after free) 48 | assert_eq!(x[0], 4); 49 | assert_eq!(z[0], 6); 50 | assert_eq!(z[1], 8); 51 | assert_eq!(reget_three[0], 0); 52 | assert_eq!(reget_three[1], 9); 53 | let mut _z = ags.alloc_cell(1); 54 | } 55 | } 56 | } 57 | #[test] 58 | fn uninitialized_stack_pool_free_null() { 59 | let mut stack_global_buffer = define_allocator_memory_pool!(8, u8, [0; 256 - 8], stack); 60 | let mut ags = StackAllocatedFreelist8::::new_allocator(&mut stack_global_buffer, uninitialized); 61 | { 62 | let s = ags.alloc_cell(0); 63 | //u.slice_mut()[0] = 4; 64 | let t = ags.alloc_cell(0); 65 | //u.slice_mut()[0] = 4; 66 | let u = ags.alloc_cell(0); 67 | //u.slice_mut()[0] = 4; 68 | let v = ags.alloc_cell(0); 69 | //v.slice_mut()[0] = 4; 70 | let ss = ags.alloc_cell(0); 71 | //u.slice_mut()[0] = 4; 72 | let tt = ags.alloc_cell(0); 73 | //u.slice_mut()[0] = 4; 74 | let uu = ags.alloc_cell(0); 75 | //u.slice_mut()[0] = 4; 76 | let vv = ags.alloc_cell(0); 77 | //v.slice_mut()[0] = 4; 78 | let mut w = ags.alloc_cell(31); 79 | w.slice_mut()[30] = 4; 80 | let mut x = ags.alloc_cell(31); 81 | x.slice_mut()[30] = 4; 82 | let mut y = ags.alloc_cell(31); 83 | y.slice_mut()[30] = 4; 84 | let mut z = ags.alloc_cell(31); 85 | z.slice_mut()[30] = 4; 86 | let mut zz = ags.alloc_cell(31); 87 | zz.slice_mut()[30] = 4; 88 | let mut xx = ags.alloc_cell(31); 89 | xx.slice_mut()[30] = 4; 90 | let mut yy = ags.alloc_cell(31); 91 | yy.slice_mut()[30] = 4; 92 | let mut ww = ags.alloc_cell(31); 93 | ww.slice_mut()[30] = 4; 94 | ags.free_cell(y); 95 | ags.free_cell(x); 96 | ags.free_cell(z); 97 | ags.free_cell(zz); 98 | ags.free_cell(xx); 99 | ags.free_cell(yy); 100 | ags.free_cell(ww); 101 | ags.free_cell(v); 102 | ags.free_cell(u); 103 | ags.free_cell(s); 104 | ags.free_cell(t); 105 | ags.free_cell(w); 106 | ags.free_cell(vv); 107 | ags.free_cell(uu); 108 | ags.free_cell(ss); 109 | ags.free_cell(tt); 110 | let mut a = ags.alloc_cell(31); 111 | a.slice_mut()[30] = 4; 112 | let mut b = ags.alloc_cell(31); 113 | b.slice_mut()[30] = 4; 114 | let mut c = ags.alloc_cell(31); 115 | c.slice_mut()[30] = 4; 116 | let mut d = ags.alloc_cell(31); 117 | d.slice_mut()[30] = 4; 118 | let mut e = ags.alloc_cell(31); 119 | e.slice_mut()[30] = 4; 120 | let mut f = ags.alloc_cell(31); 121 | f.slice_mut()[30] = 4; 122 | let mut g = ags.alloc_cell(31); 123 | g.slice_mut()[30] = 4; 124 | let mut h = ags.alloc_cell(31); 125 | h.slice_mut()[30] = 4; 126 | 127 | } 128 | 129 | } 130 | 131 | #[test] 132 | fn uninitialized_calloc_pool_test() { 133 | 134 | { 135 | let mut calloc_global_buffer = unsafe{define_allocator_memory_pool!(4096, u8, [0; 200 * 1024 * 1024], calloc)}; 136 | let mut ags = CallocAllocatedFreelist4096::::new_allocator(&mut calloc_global_buffer.data, uninitialized); 137 | { 138 | let mut x = ags.alloc_cell(9999); 139 | x.slice_mut()[0] = 4; 140 | let mut y = ags.alloc_cell(4); 141 | y[0] = 5; 142 | ags.free_cell(y); 143 | 144 | let mut three = ags.alloc_cell(3); 145 | three[0] = 6; 146 | ags.free_cell(three); 147 | 148 | let mut z = ags.alloc_cell(4); 149 | z.slice_mut()[1] = 8; 150 | let mut reget_three = ags.alloc_cell(4); 151 | reget_three.slice_mut()[1] = 9; 152 | //y.mem[0] = 6; // <-- this is an error (use after free) 153 | assert_eq!(x[0], 4); 154 | assert_eq!(z[0], 6); 155 | assert_eq!(z[1], 8); 156 | assert_eq!(reget_three[0], 0); 157 | assert_eq!(reget_three[1], 9); 158 | let mut _z = ags.alloc_cell(1); 159 | } 160 | println!("{:?}", ags.free_list_start); 161 | } 162 | } 163 | #[test] 164 | fn uninitialized_global_pool_test() { 165 | { 166 | let mut ags = GlobalAllocatedFreelist::::new_allocator(uninitialized); 167 | unsafe { 168 | bind_global_buffers_to_allocator!(ags, global_buffer, u8); 169 | } 170 | { 171 | let mut x = ags.alloc_cell(9999); 172 | x.slice_mut()[0] = 4; 173 | let mut y = ags.alloc_cell(4); 174 | y[0] = 5; 175 | ags.free_cell(y); 176 | 177 | let mut three = ags.alloc_cell(3); 178 | three[0] = 6; 179 | ags.free_cell(three); 180 | 181 | let mut z = ags.alloc_cell(4); 182 | z.slice_mut()[1] = 8; 183 | let mut reget_three = ags.alloc_cell(4); 184 | reget_three.slice_mut()[1] = 9; 185 | //y.mem[0] = 6; // <-- this is an error (use after free) 186 | assert_eq!(x[0], 4); 187 | assert_eq!(z[0], 6); 188 | assert_eq!(z[1], 8); 189 | assert_eq!(reget_three[0], 0); 190 | assert_eq!(reget_three[1], 9); 191 | let mut _z = ags.alloc_cell(1); 192 | } 193 | } 194 | } 195 | 196 | #[test] 197 | fn stack_pool_test() { 198 | { 199 | let mut stack_global_buffer = define_allocator_memory_pool!(4, u8, [0; 65536], stack); 200 | let mut ags = StackAllocatedFreelist4::::new_allocator(&mut stack_global_buffer, bzero); 201 | { 202 | let mut x = ags.alloc_cell(9999); 203 | x.slice_mut()[0] = 4; 204 | let mut y = ags.alloc_cell(4); 205 | y[0] = 5; 206 | ags.free_cell(y); 207 | 208 | let mut three = ags.alloc_cell(3); 209 | three[0] = 6; 210 | ags.free_cell(three); 211 | 212 | let mut z = ags.alloc_cell(4); 213 | z.slice_mut()[1] = 8; 214 | let mut reget_three = ags.alloc_cell(4); 215 | reget_three.slice_mut()[1] = 9; 216 | //y.mem[0] = 6; // <-- this is an error (use after free) 217 | assert_eq!(x[0], 4); 218 | assert_eq!(z[0], 0); 219 | assert_eq!(z[1], 8); 220 | assert_eq!(reget_three[0], 0); 221 | assert_eq!(reget_three[1], 9); 222 | let mut _z = ags.alloc_cell(1); 223 | } 224 | } 225 | } 226 | #[test] 227 | fn stack_pool_free_null() { 228 | let mut stack_global_buffer = define_allocator_memory_pool!(8, u8, [0; 256 - 8], stack); 229 | let mut ags = StackAllocatedFreelist8::::new_allocator(&mut stack_global_buffer, bzero); 230 | { 231 | let s = ags.alloc_cell(0); 232 | //u.slice_mut()[0] = 4; 233 | let t = ags.alloc_cell(0); 234 | //u.slice_mut()[0] = 4; 235 | let u = ags.alloc_cell(0); 236 | //u.slice_mut()[0] = 4; 237 | let v = ags.alloc_cell(0); 238 | //v.slice_mut()[0] = 4; 239 | let ss = ags.alloc_cell(0); 240 | //u.slice_mut()[0] = 4; 241 | let tt = ags.alloc_cell(0); 242 | //u.slice_mut()[0] = 4; 243 | let uu = ags.alloc_cell(0); 244 | //u.slice_mut()[0] = 4; 245 | let vv = ags.alloc_cell(0); 246 | //v.slice_mut()[0] = 4; 247 | let mut w = ags.alloc_cell(31); 248 | w.slice_mut()[30] = 4; 249 | let mut x = ags.alloc_cell(31); 250 | x.slice_mut()[30] = 4; 251 | let mut y = ags.alloc_cell(31); 252 | y.slice_mut()[30] = 4; 253 | let mut z = ags.alloc_cell(31); 254 | z.slice_mut()[30] = 4; 255 | let mut zz = ags.alloc_cell(31); 256 | zz.slice_mut()[30] = 4; 257 | let mut xx = ags.alloc_cell(31); 258 | xx.slice_mut()[30] = 4; 259 | let mut yy = ags.alloc_cell(31); 260 | yy.slice_mut()[30] = 4; 261 | let mut ww = ags.alloc_cell(31); 262 | ww.slice_mut()[30] = 4; 263 | ags.free_cell(y); 264 | ags.free_cell(x); 265 | ags.free_cell(z); 266 | ags.free_cell(zz); 267 | ags.free_cell(xx); 268 | ags.free_cell(yy); 269 | ags.free_cell(ww); 270 | ags.free_cell(v); 271 | ags.free_cell(u); 272 | ags.free_cell(s); 273 | ags.free_cell(t); 274 | ags.free_cell(w); 275 | ags.free_cell(vv); 276 | ags.free_cell(uu); 277 | ags.free_cell(ss); 278 | ags.free_cell(tt); 279 | let mut a = ags.alloc_cell(31); 280 | a.slice_mut()[30] = 4; 281 | let mut b = ags.alloc_cell(31); 282 | b.slice_mut()[30] = 4; 283 | let mut c = ags.alloc_cell(31); 284 | c.slice_mut()[30] = 4; 285 | let mut d = ags.alloc_cell(31); 286 | d.slice_mut()[30] = 4; 287 | let mut e = ags.alloc_cell(31); 288 | e.slice_mut()[30] = 4; 289 | let mut f = ags.alloc_cell(31); 290 | f.slice_mut()[30] = 4; 291 | let mut g = ags.alloc_cell(31); 292 | g.slice_mut()[30] = 4; 293 | let mut h = ags.alloc_cell(31); 294 | h.slice_mut()[30] = 4; 295 | 296 | } 297 | 298 | } 299 | 300 | #[test] 301 | fn calloc_pool_test() { 302 | 303 | { 304 | let mut calloc_global_buffer = unsafe {define_allocator_memory_pool!(4096, u8, [0; 200 * 1024 * 1024], calloc)}; 305 | let mut ags = CallocAllocatedFreelist4096::::new_allocator(&mut calloc_global_buffer.data, bzero); 306 | { 307 | let mut x = ags.alloc_cell(9999); 308 | x.slice_mut()[0] = 4; 309 | let mut y = ags.alloc_cell(4); 310 | y[0] = 5; 311 | ags.free_cell(y); 312 | 313 | let mut three = ags.alloc_cell(3); 314 | three[0] = 6; 315 | ags.free_cell(three); 316 | 317 | let mut z = ags.alloc_cell(4); 318 | z.slice_mut()[1] = 8; 319 | let mut reget_three = ags.alloc_cell(4); 320 | reget_three.slice_mut()[1] = 9; 321 | //y.mem[0] = 6; // <-- this is an error (use after free) 322 | assert_eq!(x[0], 4); 323 | assert_eq!(z[0], 0); 324 | assert_eq!(z[1], 8); 325 | assert_eq!(reget_three[0], 0); 326 | assert_eq!(reget_three[1], 9); 327 | let mut _z = ags.alloc_cell(1); 328 | } 329 | } 330 | } 331 | 332 | 333 | #[test] 334 | fn global_pool_test() { 335 | { 336 | let mut ags = GlobalAllocatedFreelist::::new_allocator(bzero); 337 | unsafe { 338 | bind_global_buffers_to_allocator!(ags, global_buffer2, u8); 339 | } 340 | { 341 | let mut x = ags.alloc_cell(9999); 342 | x.slice_mut()[0] = 4; 343 | let mut y = ags.alloc_cell(4); 344 | y[0] = 5; 345 | ags.free_cell(y); 346 | 347 | let mut three = ags.alloc_cell(3); 348 | three[0] = 6; 349 | ags.free_cell(three); 350 | 351 | let mut z = ags.alloc_cell(4); 352 | z.slice_mut()[1] = 8; 353 | let mut reget_three = ags.alloc_cell(4); 354 | reget_three.slice_mut()[1] = 9; 355 | //y.mem[0] = 6; // <-- this is an error (use after free) 356 | assert_eq!(x[0], 4); 357 | assert_eq!(z[0], 0); 358 | assert_eq!(z[1], 8); 359 | assert_eq!(reget_three[0], 0); 360 | assert_eq!(reget_three[1], 9); 361 | let mut _z = ags.alloc_cell(1); 362 | } 363 | } 364 | } 365 | 366 | 367 | -------------------------------------------------------------------------------- /alloc-stdlib/tests/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused_imports)] 2 | #![allow(dead_code)] 3 | //#![feature(trace_macros)] 4 | 5 | #[cfg(test)] 6 | 7 | #[macro_use] 8 | extern crate alloc_no_stdlib; 9 | extern crate alloc_stdlib; 10 | 11 | extern crate core; 12 | use core::ops; 13 | use alloc_no_stdlib::{Allocator, SliceWrapperMut, SliceWrapper, 14 | StackAllocator, AllocatedStackMemory, uninitialized, bzero}; 15 | 16 | use alloc_stdlib::{HeapPrealloc, HeapAlloc}; 17 | #[cfg(feature="unsafe")] 18 | use alloc_stdlib::{HeapAllocUninitialized}; 19 | 20 | declare_stack_allocator_struct!(CallocAllocatedFreelist4096, 4096, calloc); 21 | declare_stack_allocator_struct!(StackAllocatedFreelist4, 4, stack); 22 | declare_stack_allocator_struct!(StackAllocatedFreelist8, 8, stack); 23 | declare_stack_allocator_struct!(GlobalAllocatedFreelist, 16, global); 24 | //trace_macros!(true); 25 | 26 | define_allocator_memory_pool!(16, u8, [0; 1024 * 1024 * 100], global, global_buffer); 27 | define_allocator_memory_pool!(16, u8, [0; 1024 * 1024 * 100], global, global_buffer2); 28 | extern { 29 | fn calloc(n_elem : usize, el_size : usize) -> *mut u8; 30 | fn malloc(len : usize) -> *mut u8; 31 | fn free(item : *mut u8); 32 | } 33 | #[test] 34 | fn uninitialized_stack_pool_test() { 35 | { 36 | let mut stack_global_buffer = define_allocator_memory_pool!(4, u8, [0; 65536], stack); 37 | let mut ags = StackAllocatedFreelist4::::new_allocator(&mut stack_global_buffer, uninitialized); 38 | { 39 | let mut x = ags.alloc_cell(9999); 40 | x.slice_mut()[0] = 4; 41 | let mut y = ags.alloc_cell(4); 42 | y[0] = 5; 43 | ags.free_cell(y); 44 | 45 | let mut three = ags.alloc_cell(3); 46 | three[0] = 6; 47 | ags.free_cell(three); 48 | 49 | let mut z = ags.alloc_cell(4); 50 | z.slice_mut()[1] = 8; 51 | let mut reget_three = ags.alloc_cell(4); 52 | reget_three.slice_mut()[1] = 9; 53 | //y.mem[0] = 6; // <-- this is an error (use after free) 54 | assert_eq!(x[0], 4); 55 | assert_eq!(z[0], 6); 56 | assert_eq!(z[1], 8); 57 | assert_eq!(reget_three[0], 0); 58 | assert_eq!(reget_three[1], 9); 59 | let mut _z = ags.alloc_cell(1); 60 | } 61 | } 62 | } 63 | #[test] 64 | fn uninitialized_stack_pool_free_null() { 65 | let mut stack_global_buffer = define_allocator_memory_pool!(8, u8, [0; 256 - 8], stack); 66 | let mut ags = StackAllocatedFreelist8::::new_allocator(&mut stack_global_buffer, uninitialized); 67 | { 68 | let s = ags.alloc_cell(0); 69 | //u.slice_mut()[0] = 4; 70 | let t = ags.alloc_cell(0); 71 | //u.slice_mut()[0] = 4; 72 | let u = ags.alloc_cell(0); 73 | //u.slice_mut()[0] = 4; 74 | let v = ags.alloc_cell(0); 75 | //v.slice_mut()[0] = 4; 76 | let ss = ags.alloc_cell(0); 77 | //u.slice_mut()[0] = 4; 78 | let tt = ags.alloc_cell(0); 79 | //u.slice_mut()[0] = 4; 80 | let uu = ags.alloc_cell(0); 81 | //u.slice_mut()[0] = 4; 82 | let vv = ags.alloc_cell(0); 83 | //v.slice_mut()[0] = 4; 84 | let mut w = ags.alloc_cell(31); 85 | w.slice_mut()[30] = 4; 86 | let mut x = ags.alloc_cell(31); 87 | x.slice_mut()[30] = 4; 88 | let mut y = ags.alloc_cell(31); 89 | y.slice_mut()[30] = 4; 90 | let mut z = ags.alloc_cell(31); 91 | z.slice_mut()[30] = 4; 92 | let mut zz = ags.alloc_cell(31); 93 | zz.slice_mut()[30] = 4; 94 | let mut xx = ags.alloc_cell(31); 95 | xx.slice_mut()[30] = 4; 96 | let mut yy = ags.alloc_cell(31); 97 | yy.slice_mut()[30] = 4; 98 | let mut ww = ags.alloc_cell(31); 99 | ww.slice_mut()[30] = 4; 100 | ags.free_cell(y); 101 | ags.free_cell(x); 102 | ags.free_cell(z); 103 | ags.free_cell(zz); 104 | ags.free_cell(xx); 105 | ags.free_cell(yy); 106 | ags.free_cell(ww); 107 | ags.free_cell(v); 108 | ags.free_cell(u); 109 | ags.free_cell(s); 110 | ags.free_cell(t); 111 | ags.free_cell(w); 112 | ags.free_cell(vv); 113 | ags.free_cell(uu); 114 | ags.free_cell(ss); 115 | ags.free_cell(tt); 116 | let mut a = ags.alloc_cell(31); 117 | a.slice_mut()[30] = 4; 118 | let mut b = ags.alloc_cell(31); 119 | b.slice_mut()[30] = 4; 120 | let mut c = ags.alloc_cell(31); 121 | c.slice_mut()[30] = 4; 122 | let mut d = ags.alloc_cell(31); 123 | d.slice_mut()[30] = 4; 124 | let mut e = ags.alloc_cell(31); 125 | e.slice_mut()[30] = 4; 126 | let mut f = ags.alloc_cell(31); 127 | f.slice_mut()[30] = 4; 128 | let mut g = ags.alloc_cell(31); 129 | g.slice_mut()[30] = 4; 130 | let mut h = ags.alloc_cell(31); 131 | h.slice_mut()[30] = 4; 132 | 133 | } 134 | 135 | } 136 | #[test] 137 | #[cfg(all(feature="unsafe",not(feature="no-stdlib")))] 138 | fn uninitialized_heap_pool_test() { 139 | { 140 | let mut heap_global_buffer = unsafe{HeapPrealloc::::new_uninitialized_memory_pool(6 * 1024 * 1024)}; 141 | let mut ags = HeapPrealloc::::new_allocator(4096, &mut heap_global_buffer, uninitialized); 142 | { 143 | let mut x = ags.alloc_cell(9999); 144 | x.slice_mut()[0] = 4; 145 | let mut y = ags.alloc_cell(4); 146 | y[0] = 5; 147 | ags.free_cell(y); 148 | 149 | let mut three = ags.alloc_cell(3); 150 | three[0] = 6; 151 | ags.free_cell(three); 152 | 153 | let mut z = ags.alloc_cell(4); 154 | z.slice_mut()[1] = 8; 155 | let mut reget_three = ags.alloc_cell(4); 156 | reget_three.slice_mut()[1] = 9; 157 | //y.mem[0] = 6; // <-- this is an error (use after free) 158 | assert_eq!(x[0], 4); 159 | assert_eq!(z[0], 6); 160 | assert_eq!(z[1], 8); 161 | // assert_eq!(reget_three[0], 0); // not valid: uninitialized heap memory 162 | assert_eq!(reget_three[1], 9); 163 | let mut _z = ags.alloc_cell(1); 164 | } 165 | } 166 | } 167 | #[test] 168 | fn uninitialized_calloc_pool_test() { 169 | 170 | { 171 | let mut calloc_global_buffer = unsafe{define_allocator_memory_pool!(4096, u8, [0; 200 * 1024 * 1024], calloc)}; 172 | let mut ags = CallocAllocatedFreelist4096::::new_allocator(&mut calloc_global_buffer.data, uninitialized); 173 | { 174 | let mut x = ags.alloc_cell(9999); 175 | x.slice_mut()[0] = 4; 176 | let mut y = ags.alloc_cell(4); 177 | y[0] = 5; 178 | ags.free_cell(y); 179 | 180 | let mut three = ags.alloc_cell(3); 181 | three[0] = 6; 182 | ags.free_cell(three); 183 | 184 | let mut z = ags.alloc_cell(4); 185 | z.slice_mut()[1] = 8; 186 | let mut reget_three = ags.alloc_cell(4); 187 | reget_three.slice_mut()[1] = 9; 188 | //y.mem[0] = 6; // <-- this is an error (use after free) 189 | assert_eq!(x[0], 4); 190 | assert_eq!(z[0], 6); 191 | assert_eq!(z[1], 8); 192 | assert_eq!(reget_three[0], 0); // since we have control over this buffer and the free strategy: this should be zero 193 | assert_eq!(reget_three[1], 9); 194 | let mut _z = ags.alloc_cell(1); 195 | } 196 | println!("{:?}", ags.free_list_start); 197 | } 198 | } 199 | #[test] 200 | fn uninitialized_global_pool_test() { 201 | { 202 | let mut ags = GlobalAllocatedFreelist::::new_allocator(uninitialized); 203 | unsafe { 204 | bind_global_buffers_to_allocator!(ags, global_buffer, u8); 205 | } 206 | { 207 | let mut x = ags.alloc_cell(9999); 208 | x.slice_mut()[0] = 4; 209 | let mut y = ags.alloc_cell(4); 210 | y[0] = 5; 211 | ags.free_cell(y); 212 | 213 | let mut three = ags.alloc_cell(3); 214 | three[0] = 6; 215 | ags.free_cell(three); 216 | 217 | let mut z = ags.alloc_cell(4); 218 | z.slice_mut()[1] = 8; 219 | let mut reget_three = ags.alloc_cell(4); 220 | reget_three.slice_mut()[1] = 9; 221 | //y.mem[0] = 6; // <-- this is an error (use after free) 222 | assert_eq!(x[0], 4); 223 | assert_eq!(z[0], 6); 224 | assert_eq!(z[1], 8); 225 | assert_eq!(reget_three[0], 0); 226 | assert_eq!(reget_three[1], 9); 227 | let mut _z = ags.alloc_cell(1); 228 | } 229 | } 230 | } 231 | 232 | #[test] 233 | fn stack_pool_test() { 234 | { 235 | let mut stack_global_buffer = define_allocator_memory_pool!(4, u8, [0; 65536], stack); 236 | let mut ags = StackAllocatedFreelist4::::new_allocator(&mut stack_global_buffer, bzero); 237 | { 238 | let mut x = ags.alloc_cell(9999); 239 | x.slice_mut()[0] = 4; 240 | let mut y = ags.alloc_cell(4); 241 | y[0] = 5; 242 | ags.free_cell(y); 243 | 244 | let mut three = ags.alloc_cell(3); 245 | three[0] = 6; 246 | ags.free_cell(three); 247 | 248 | let mut z = ags.alloc_cell(4); 249 | z.slice_mut()[1] = 8; 250 | let mut reget_three = ags.alloc_cell(4); 251 | reget_three.slice_mut()[1] = 9; 252 | //y.mem[0] = 6; // <-- this is an error (use after free) 253 | assert_eq!(x[0], 4); 254 | assert_eq!(z[0], 0); 255 | assert_eq!(z[1], 8); 256 | assert_eq!(reget_three[0], 0); 257 | assert_eq!(reget_three[1], 9); 258 | let mut _z = ags.alloc_cell(1); 259 | } 260 | } 261 | } 262 | #[test] 263 | fn stack_pool_free_null() { 264 | let mut stack_global_buffer = define_allocator_memory_pool!(8, u8, [0; 256 - 8], stack); 265 | let mut ags = StackAllocatedFreelist8::::new_allocator(&mut stack_global_buffer, bzero); 266 | { 267 | let s = ags.alloc_cell(0); 268 | //u.slice_mut()[0] = 4; 269 | let t = ags.alloc_cell(0); 270 | //u.slice_mut()[0] = 4; 271 | let u = ags.alloc_cell(0); 272 | //u.slice_mut()[0] = 4; 273 | let v = ags.alloc_cell(0); 274 | //v.slice_mut()[0] = 4; 275 | let ss = ags.alloc_cell(0); 276 | //u.slice_mut()[0] = 4; 277 | let tt = ags.alloc_cell(0); 278 | //u.slice_mut()[0] = 4; 279 | let uu = ags.alloc_cell(0); 280 | //u.slice_mut()[0] = 4; 281 | let vv = ags.alloc_cell(0); 282 | //v.slice_mut()[0] = 4; 283 | let mut w = ags.alloc_cell(31); 284 | w.slice_mut()[30] = 4; 285 | let mut x = ags.alloc_cell(31); 286 | x.slice_mut()[30] = 4; 287 | let mut y = ags.alloc_cell(31); 288 | y.slice_mut()[30] = 4; 289 | let mut z = ags.alloc_cell(31); 290 | z.slice_mut()[30] = 4; 291 | let mut zz = ags.alloc_cell(31); 292 | zz.slice_mut()[30] = 4; 293 | let mut xx = ags.alloc_cell(31); 294 | xx.slice_mut()[30] = 4; 295 | let mut yy = ags.alloc_cell(31); 296 | yy.slice_mut()[30] = 4; 297 | let mut ww = ags.alloc_cell(31); 298 | ww.slice_mut()[30] = 4; 299 | ags.free_cell(y); 300 | ags.free_cell(x); 301 | ags.free_cell(z); 302 | ags.free_cell(zz); 303 | ags.free_cell(xx); 304 | ags.free_cell(yy); 305 | ags.free_cell(ww); 306 | ags.free_cell(v); 307 | ags.free_cell(u); 308 | ags.free_cell(s); 309 | ags.free_cell(t); 310 | ags.free_cell(w); 311 | ags.free_cell(vv); 312 | ags.free_cell(uu); 313 | ags.free_cell(ss); 314 | ags.free_cell(tt); 315 | let mut a = ags.alloc_cell(31); 316 | a.slice_mut()[30] = 4; 317 | let mut b = ags.alloc_cell(31); 318 | b.slice_mut()[30] = 4; 319 | let mut c = ags.alloc_cell(31); 320 | c.slice_mut()[30] = 4; 321 | let mut d = ags.alloc_cell(31); 322 | d.slice_mut()[30] = 4; 323 | let mut e = ags.alloc_cell(31); 324 | e.slice_mut()[30] = 4; 325 | let mut f = ags.alloc_cell(31); 326 | f.slice_mut()[30] = 4; 327 | let mut g = ags.alloc_cell(31); 328 | g.slice_mut()[30] = 4; 329 | let mut h = ags.alloc_cell(31); 330 | h.slice_mut()[30] = 4; 331 | 332 | } 333 | 334 | } 335 | #[test] 336 | #[cfg(not(feature="no-stdlib"))] 337 | fn heap_pool_test() { 338 | { 339 | let mut heap_global_buffer = define_allocator_memory_pool!(4096, u8, [0; 6 * 1024 * 1024], heap); 340 | let mut ags = HeapPrealloc::::new_allocator(4096, &mut heap_global_buffer, bzero); 341 | { 342 | let mut x = ags.alloc_cell(9999); 343 | x.slice_mut()[0] = 4; 344 | let mut y = ags.alloc_cell(4); 345 | y[0] = 5; 346 | ags.free_cell(y); 347 | 348 | let mut three = ags.alloc_cell(3); 349 | three[0] = 6; 350 | ags.free_cell(three); 351 | 352 | let mut z = ags.alloc_cell(4); 353 | z.slice_mut()[1] = 8; 354 | let mut reget_three = ags.alloc_cell(4); 355 | reget_three.slice_mut()[1] = 9; 356 | //y.mem[0] = 6; // <-- this is an error (use after free) 357 | assert_eq!(x[0], 4); 358 | assert_eq!(z[0], 0); 359 | assert_eq!(z[1], 8); 360 | assert_eq!(reget_three[0], 0); 361 | assert_eq!(reget_three[1], 9); 362 | let mut _z = ags.alloc_cell(1); 363 | } 364 | } 365 | } 366 | 367 | 368 | 369 | #[test] 370 | fn calloc_pool_test() { 371 | 372 | { 373 | let mut calloc_global_buffer = unsafe {define_allocator_memory_pool!(4096, u8, [0; 200 * 1024 * 1024], calloc)}; 374 | { 375 | let mut ags = CallocAllocatedFreelist4096::::new_allocator(&mut calloc_global_buffer.data, bzero); 376 | { 377 | let mut x = ags.alloc_cell(9999); 378 | x.slice_mut()[0] = 4; 379 | let mut y = ags.alloc_cell(4); 380 | y[0] = 5; 381 | ags.free_cell(y); 382 | 383 | let mut three = ags.alloc_cell(3); 384 | three[0] = 6; 385 | ags.free_cell(three); 386 | 387 | let mut z = ags.alloc_cell(4); 388 | z.slice_mut()[1] = 8; 389 | let mut reget_three = ags.alloc_cell(4); 390 | reget_three.slice_mut()[1] = 9; 391 | //y.mem[0] = 6; // <-- this is an error (use after free) 392 | assert_eq!(x[0], 4); 393 | assert_eq!(z[0], 0); 394 | assert_eq!(z[1], 8); 395 | assert_eq!(reget_three[0], 0); 396 | assert_eq!(reget_three[1], 9); 397 | let mut _z = ags.alloc_cell(1); 398 | } 399 | } 400 | { 401 | let mut ags = CallocAllocatedFreelist4096::::new_allocator(&mut calloc_global_buffer.data, bzero); 402 | { 403 | let mut x = ags.alloc_cell(9999); 404 | x.slice_mut()[0] = 4; 405 | let mut y = ags.alloc_cell(4); 406 | y[0] = 5; 407 | ags.free_cell(y); 408 | 409 | let mut three = ags.alloc_cell(3); 410 | three[0] = 6; 411 | ags.free_cell(three); 412 | 413 | let mut z = ags.alloc_cell(4); 414 | z.slice_mut()[1] = 8; 415 | let mut reget_three = ags.alloc_cell(4); 416 | reget_three.slice_mut()[1] = 9; 417 | //y.mem[0] = 6; // <-- this is an error (use after free) 418 | assert_eq!(x[0], 4); 419 | assert_eq!(z[0], 0); 420 | assert_eq!(z[1], 8); 421 | assert_eq!(reget_three[0], 0); 422 | assert_eq!(reget_three[1], 9); 423 | let mut _z = ags.alloc_cell(1); 424 | } 425 | } 426 | drop(calloc_global_buffer); 427 | } 428 | } 429 | 430 | 431 | 432 | 433 | #[test] 434 | fn global_pool_test() { 435 | { 436 | let mut ags = GlobalAllocatedFreelist::::new_allocator(bzero); 437 | unsafe { 438 | bind_global_buffers_to_allocator!(ags, global_buffer2, u8); 439 | } 440 | { 441 | let mut x = ags.alloc_cell(9999); 442 | x.slice_mut()[0] = 4; 443 | let mut y = ags.alloc_cell(4); 444 | y[0] = 5; 445 | ags.free_cell(y); 446 | 447 | let mut three = ags.alloc_cell(3); 448 | three[0] = 6; 449 | ags.free_cell(three); 450 | 451 | let mut z = ags.alloc_cell(4); 452 | z.slice_mut()[1] = 8; 453 | let mut reget_three = ags.alloc_cell(4); 454 | reget_three.slice_mut()[1] = 9; 455 | //y.mem[0] = 6; // <-- this is an error (use after free) 456 | assert_eq!(x[0], 4); 457 | assert_eq!(z[0], 0); 458 | assert_eq!(z[1], 8); 459 | assert_eq!(reget_three[0], 0); 460 | assert_eq!(reget_three[1], 9); 461 | let mut _z = ags.alloc_cell(1); 462 | } 463 | } 464 | } 465 | 466 | 467 | --------------------------------------------------------------------------------