alloc-no-stdlib-2.0.4/.cargo_vcs_info.json0000644000000001360000000000100140220ustar { "git": { "sha1": "6032b6a9b20e03737135c55a0270ccffcc1438ef" }, "path_in_vcs": "" }alloc-no-stdlib-2.0.4/.gitignore000064400000000000000000000000221046102023000145740ustar 00000000000000Cargo.lock target alloc-no-stdlib-2.0.4/.travis.yml000064400000000000000000000005671046102023000147330ustar 00000000000000language: rust rust: - nightly - stable - 1.12.0 - 1.8.0 os: - linux - osx script: - cargo test - cargo test --features=unsafe --release - cd alloc-stdlib && cargo test && cd .. - cd alloc-stdlib && cargo test --release --features=unsafe && cd .. - cd alloc-stdlib && cargo test --release && cd .. matrix: exclude: - rust: 1.8.0 os: osx alloc-no-stdlib-2.0.4/Cargo.lock0000644000000002370000000000100117770ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "alloc-no-stdlib" version = "2.0.4" alloc-no-stdlib-2.0.4/Cargo.toml0000644000000025030000000000100120200ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] name = "alloc-no-stdlib" version = "2.0.4" authors = ["Daniel Reiter Horn "] autobins = false 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" homepage = "https://github.com/dropbox/rust-alloc-no-stdlib" documentation = "https://raw.githubusercontent.com/dropbox/rust-alloc-no-stdlib/master/tests/lib.rs" readme = "README.md" keywords = [ "custom", "allocator", "calloc", "safe", "nostd", ] license = "BSD-3-Clause" repository = "https://github.com/dropbox/rust-alloc-no-stdlib" [[bin]] name = "example" [features] unsafe = [] alloc-no-stdlib-2.0.4/Cargo.toml.orig000064400000000000000000000015311046102023000155010ustar 00000000000000[package] name = "alloc-no-stdlib" 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" version = "2.0.4" authors = ["Daniel Reiter Horn "] documentation = "https://raw.githubusercontent.com/dropbox/rust-alloc-no-stdlib/master/tests/lib.rs" homepage = "https://github.com/dropbox/rust-alloc-no-stdlib" readme = "README.md" keywords = ["custom", "allocator", "calloc", "safe", "nostd"] license = "BSD-3-Clause" repository = "https://github.com/dropbox/rust-alloc-no-stdlib" autobins = false [[bin]] name = "example" [features] unsafe = [] alloc-no-stdlib-2.0.4/LICENSE000064400000000000000000000027131046102023000136220ustar 00000000000000Copyright (c) 2016 Dropbox, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 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. 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. 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. alloc-no-stdlib-2.0.4/README.md000064400000000000000000000161211046102023000140720ustar 00000000000000# Framework for allocating memory in #![no_std] modules. [![crates.io](http://meritbadge.herokuapp.com/alloc-no-stdlib)](https://crates.io/crates/alloc-no-stdlib) [![Build Status](https://travis-ci.org/dropbox/rust-alloc-no-stdlib.svg?branch=master)](https://travis-ci.org/dropbox/rust-alloc-no-stdlib) ## Requirements * Rust 1.6 ## Documentation Currently there is no standard way to allocate memory from within a module that is no_std. This provides a mechanism to describe a memory allocation that can be satisfied entirely on the stack, by unsafely linking to calloc, or by unsafely referencing a mutable global variable. This library currently will leak memory if free_cell isn't specifically invoked on memory. However, if linked by a library that actually can depend on the stdlib then that library can simply pass in a few allocators and use the standard Box allocation and will free automatically. This library should also make it possible to entirely jail a rust application that needs dynamic allocations by preallocating a maximum limit of data upfront using calloc and using seccomp to disallow future syscalls. ## Usage There are 3 modes for allocating memory, each with advantages and disadvantages ### On the stack This is possible without the stdlib at all However, this eats into the natural ulimit on the stack depth and generally limits the program to only a few megs of dynamically allocated data Example: ```rust // First define a struct to hold all the array on the stack. declare_stack_allocator_struct!(StackAllocatedFreelist4, 4, stack); // since generics cannot be used, the actual struct to hold the memory must be defined with a macro ... // in the code where the memory must be used, first the array needs to be readied let mut stack_buffer = define_allocator_memory_pool!(4, u8, [0; 65536], stack); // then an allocator needs to be made and pointed to the stack_buffer on the stack // the final argument tells the system if free'd data should be zero'd before being // reused by a subsequent call to alloc_cell let mut ags = StackAllocatedFreelist4::::new_allocator(&mut stack_buffer, bzero); { // now we can get memory dynamically let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; // get more memory let mut y = ags.alloc_cell(4); y[0] = 5; // and free it, consuming the buffer ags.free_cell(y); //y.mem[0] = 6; // <-- this is an error: won't compile (use after free) assert_eq!(x[0], 4); ``` ### On the heap This uses the standard Box facilities to allocate memory ```rust let mut halloc = HeapAlloc::::new(0); for _i in 1..10 { // heap test let mut x = halloc.alloc_cell(100000); x[0] = 4; let mut y = halloc.alloc_cell(110000); y[0] = 5; let mut z = halloc.alloc_cell(120000); z[0] = 6; assert_eq!(y[0], 5); halloc.free_cell(y); assert_eq!(x[0], 4); assert_eq!(x[9], 0); assert_eq!(z[0], 6); } ``` ### On the heap, but uninitialized This does allocate data every time it is requested, but it does not allocate the memory, so naturally it is unsafe. The caller must initialize the memory properly ```rust let mut halloc = unsafe{HeapAllocUninitialized::::new()}; { // heap test let mut x = halloc.alloc_cell(100000); x[0] = 4; let mut y = halloc.alloc_cell(110000); y[0] = 5; let mut z = halloc.alloc_cell(120000); z[0] = 6; assert_eq!(y[0], 5); halloc.free_cell(y); assert_eq!(x[0], 4); assert_eq!(x[9], 0); assert_eq!(z[0], 6); ... } ``` ### On the heap in a single pool allocation This does a single big allocation on the heap, after which no further usage of the stdlib will happen. This can be useful for a jailed application that wishes to restrict syscalls at this point ```rust use alloc_no_stdlib::HeapPrealloc; ... let mut heap_global_buffer = define_allocator_memory_pool!(4096, u8, [0; 6 * 1024 * 1024], heap); let mut ags = HeapPrealloc::::new_allocator(4096, &mut heap_global_buffer, uninitialized); { let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; let mut y = ags.alloc_cell(4); y[0] = 5; ags.free_cell(y); //y.mem[0] = 6; // <-- this is an error (use after free) } ``` ### On the heap, uninitialized This does a single big allocation on the heap, after which no further usage of the stdlib will happen. This can be useful for a jailed application that wishes to restrict syscalls at this point. This option keep does not set the memory to a valid value, so it is necessarily marked unsafe ```rust use alloc_no_stdlib::HeapPrealloc; ... let mut heap_global_buffer = unsafe{HeapPrealloc::::new_uninitialized_memory_pool(6 * 1024 * 1024)}; let mut ags = HeapPrealloc::::new_allocator(4096, &mut heap_global_buffer, uninitialized); { let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; let mut y = ags.alloc_cell(4); y[0] = 5; ags.free_cell(y); //y.mem[0] = 6; // <-- this is an error (use after free) } ``` ### With calloc This is the most efficient way to get a zero'd dynamically sized buffer without the stdlib It does invoke the C calloc function and hence must invoke unsafe code. In this version, the number of cells are fixed to the parameter specified in the struct definition (4096 in this example) ```rust extern { fn calloc(n_elem : usize, el_size : usize) -> *mut u8; fn malloc(len : usize) -> *mut u8; fn free(item : *mut u8); } declare_stack_allocator_struct!(CallocAllocatedFreelist4096, 4096, calloc); ... // the buffer is defined with 200 megs of zero'd memory from calloc let mut calloc_global_buffer = unsafe {define_allocator_memory_pool!(4096, u8, [0; 200 * 1024 * 1024], calloc)}; // and assigned to a new_allocator let mut ags = CallocAllocatedFreelist4096::::new_allocator(&mut calloc_global_buffer.data, bzero); { let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; let mut y = ags.alloc_cell(4); y[0] = 5; ags.free_cell(y); //y.mem[0] = 6; // <-- this is an error (use after free) } ``` ### With a static, mutable buffer If a single buffer of data is needed for the entire span of the application Then the simplest way to do so without a zero operation on the memory and without using the stdlib is to simply have a global allocated structure. Accessing mutable static variables requires unsafe code; however, so this code will invoke an unsafe block. Make sure to only reference global_buffer in a single place, at a single time in the code If it is used from two places or at different times, undefined behavior may result, since multiple allocators may get access to global_buffer. ```rust declare_stack_allocator_struct!(GlobalAllocatedFreelist, 16, global); define_allocator_memory_pool!(16, u8, [0; 1024 * 1024 * 100], global, global_buffer); ... // this references a global buffer let mut ags = GlobalAllocatedFreelist::::new_allocator(bzero); unsafe { bind_global_buffers_to_allocator!(ags, global_buffer, u8); } { let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; let mut y = ags.alloc_cell(4); y[0] = 5; ags.free_cell(y); //y.mem[0] = 6; // <-- this is an error (use after free) } ``` ## Contributors - Daniel Reiter Horn alloc-no-stdlib-2.0.4/src/allocated_memory/index_macro.rs000075500000000000000000000116261046102023000215700ustar 00000000000000#[macro_export] macro_rules! define_index_ops_mut { ($T:ident, $MemoryType:ty) => { impl<$T> ::core::ops::Index for $MemoryType { type Output = T; #[inline] fn index(&self, index: usize) -> &Self::Output { ::core::ops::Index::index(&**self, index) } } impl<$T> ::core::ops::IndexMut for $MemoryType { #[inline] fn index_mut(&mut self, index: usize) -> &mut Self::Output { ::core::ops::IndexMut::index_mut(&mut **self, index) } } impl<$T> ::core::ops::Index<::core::ops::Range> for $MemoryType { type Output = [T]; #[inline] fn index(&self, index: ::core::ops::Range) -> &Self::Output { ::core::ops::Index::index(&**self, index) } } impl<$T> ::core::ops::IndexMut<::core::ops::Range> for $MemoryType { #[inline] fn index_mut(&mut self, index: ::core::ops::Range) -> &mut Self::Output { ::core::ops::IndexMut::index_mut(&mut **self, index) } } impl<$T> ::core::ops::Deref for $MemoryType { type Target = [T]; fn deref(&self) -> &[T] { self.slice() } } impl ::core::ops::DerefMut for $MemoryType { fn deref_mut(&mut self) -> &mut [T] { self.slice_mut() } } }; ($T0: ident, $T:ident, $MemoryType:ty) => { impl<'a, $T> ::core::ops::Index for $MemoryType { type Output = T; #[inline] fn index(&self, index: usize) -> &Self::Output { ::core::ops::Index::index(&**self, index) } } impl<'a, $T> ::core::ops::IndexMut for $MemoryType { #[inline] fn index_mut(&mut self, index: usize) -> &mut Self::Output { ::core::ops::IndexMut::index_mut(&mut **self, index) } } impl<'a, $T> ::core::ops::Index<::core::ops::Range> for $MemoryType { type Output = [T]; #[inline] fn index(&self, index: ::core::ops::Range) -> &Self::Output { ::core::ops::Index::index(&**self, index) } } impl<'a, $T> ::core::ops::IndexMut<::core::ops::Range> for $MemoryType { #[inline] fn index_mut(&mut self, index: ::core::ops::Range) -> &mut Self::Output { ::core::ops::IndexMut::index_mut(&mut **self, index) } } impl<'a, $T> ::core::ops::Deref for $MemoryType { type Target = [T]; fn deref(&self) -> &[T] { self.slice() } } impl<'a, $T> ::core::ops::DerefMut for $MemoryType { fn deref_mut(&mut self) -> &mut [T] { self.slice_mut() } } } } #[macro_export] macro_rules! define_index_ops { ($T:ident, $MemoryType:ty) => { impl<$T> ::core::ops::Index for $MemoryType { type Output = T; #[inline] fn index(&self, index: usize) -> &Self::Output { ::core::ops::Index::index(&**self, index) } } impl<$T> ::core::ops::Index<::core::ops::Range> for $MemoryType { type Output = [T]; #[inline] fn index(&self, index: ::core::ops::Range) -> &Self::Output { ::core::ops::Index::index(&**self, index) } } impl<$T> ::core::ops::Deref for $MemoryType { type Target = [T]; fn deref(&self) -> &[T] { self.slice() } } }; ($T0: tt, $T:ident, $MemoryType:ty) => { impl<'a, $T> ::core::ops::Index for $MemoryType { type Output = T; #[inline] fn index(&self, index: usize) -> &Self::Output { ::core::ops::Index::index(&**self, index) } } impl<'a, $T> ::core::ops::Index<::core::ops::Range> for $MemoryType { type Output = [T]; #[inline] fn index(&self, index: ::core::ops::Range) -> &Self::Output { ::core::ops::Index::index(&**self, index) } } impl<'a, $T> ::core::ops::Deref for $MemoryType { type Target = [T]; fn deref(&self) -> &[T] { self.slice() } } } } alloc-no-stdlib-2.0.4/src/allocated_memory/mod.rs000064400000000000000000000010551046102023000200470ustar 00000000000000extern crate core; #[macro_use] mod index_macro; use core::default::Default; pub use core::ops::IndexMut; pub use core::ops::Index; pub use core::ops::Range; pub trait SliceWrapper { fn slice(& self) -> & [T]; fn len(&self) -> usize{ self.slice().len() } } pub trait SliceWrapperMut : SliceWrapper { fn slice_mut (&mut self) -> & mut [T]; } pub trait AllocatedSlice : SliceWrapperMut + SliceWrapper + Default { } impl AllocatedSlice for U where U : SliceWrapperMut + SliceWrapper + Default { } alloc-no-stdlib-2.0.4/src/allocated_stack_memory.rs000064400000000000000000000012741046102023000204600ustar 00000000000000extern crate core; use super::allocated_memory::SliceWrapper; use super::allocated_memory::SliceWrapperMut; pub struct AllocatedStackMemory<'a, T:'a> { pub mem : &'a mut [T], } define_index_ops_mut!(a, T, AllocatedStackMemory<'a, T>); impl<'a, T: 'a> core::default::Default for AllocatedStackMemory<'a, T> { fn default() -> Self { return AllocatedStackMemory::<'a, T>{mem : &mut[]}; } } impl<'a, T: 'a> SliceWrapper for AllocatedStackMemory<'a, T> { fn slice(& self) -> & [T] { return & self.mem; } } impl<'a, T: 'a> SliceWrapperMut for AllocatedStackMemory<'a, T> { fn slice_mut(& mut self) ->& mut [T] { return &mut self.mem; } } alloc-no-stdlib-2.0.4/src/allocator.rs000064400000000000000000000003211046102023000157230ustar 00000000000000 pub trait Allocator { type AllocatedMemory : super::AllocatedSlice; fn alloc_cell(&mut self, len : usize) -> Self::AllocatedMemory; fn free_cell(&mut self, data : Self::AllocatedMemory); } alloc-no-stdlib-2.0.4/src/bin/example.rs000064400000000000000000000065501046102023000161600ustar 00000000000000//#![feature(trace_macros)] #[macro_use] extern crate alloc_no_stdlib; extern crate core; use core::ops; mod heap_alloc; pub use heap_alloc::HeapAllocator; mod tests; extern { fn calloc(n_elem : usize, el_size : usize) -> *mut u8; } extern { fn free(ptr : *mut u8); } //use alloc::AllocatedSlice; use alloc_no_stdlib::SliceWrapper; use alloc_no_stdlib::SliceWrapperMut; use alloc_no_stdlib::AllocatedStackMemory; use alloc_no_stdlib::Allocator; use alloc_no_stdlib::StackAllocator; use alloc_no_stdlib::bzero; declare_stack_allocator_struct!(CallocAllocatedFreelist4, 4, calloc); declare_stack_allocator_struct!(StackAllocatedFreelist16, 16, stack); #[repr(C)] #[derive(PartialEq, Copy, Clone, Debug)] pub struct HuffmanCode { pub value: u16, // symbol value or table offset pub bits: u8, // number of bits used for this symbol } impl Default for HuffmanCode { fn default() -> Self { HuffmanCode { value: 0, bits: 0, } } } fn main() { let mut global_buffer = unsafe {define_allocator_memory_pool!(4, u8, [0; 1024 * 1024 * 200], calloc)}; { let gbref = &mut global_buffer; { let mut ags = CallocAllocatedFreelist4::::new_allocator(gbref.data, bzero); { let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; let mut y = ags.alloc_cell(4); y[0] = 5; ags.free_cell(y); let mut three = ags.alloc_cell(3); three[0] = 6; ags.free_cell(three); let mut z = ags.alloc_cell(4); z.slice_mut()[1] = 8; let mut reget_three = ags.alloc_cell(4); reget_three.slice_mut()[1] = 9; //y.mem[0] = 6; // <-- this is an error (use after free) println!("x[0] = {:?} z[0] = {:?} z[1] = {:?} r3[0] = {:?} r3[1] = {:?}", x.mem[0], z.mem[0], z.mem[1], reget_three[0], reget_three.slice()[1]); let mut _z = ags.alloc_cell(1); } } } let mut stack_global_buffer = define_allocator_memory_pool!(16, u8, [0; 1024 * 1024], stack); let mut stack_global_buffer_hc = define_allocator_memory_pool!(16, HuffmanCode, [HuffmanCode::default(); 1024 * 1024], stack); { let mut stackallocatorhc = StackAllocatedFreelist16::::new_allocator(&mut stack_global_buffer_hc, bzero); stackallocatorhc.alloc_cell(9999); } let mut stackallocator = StackAllocatedFreelist16::::new_allocator(&mut stack_global_buffer, bzero); { let mut x = stackallocator.alloc_cell(9999); x.slice_mut()[0] = 3; let mut y = stackallocator.alloc_cell(4); y[0] = 5; stackallocator.free_cell(y); let mut three = stackallocator.alloc_cell(3); three[0] = 6; stackallocator.free_cell(three); let mut z = stackallocator.alloc_cell(4); z.slice_mut()[1] = 8; let mut reget_three = stackallocator.alloc_cell(4); reget_three.slice_mut()[1] = 9; //y.mem[0] = 6; // <-- this is an error (use after free) println!("x[0] = {:?} z[0] = {:?} z[1] = {:?} r3[0] = {:?} r3[1] = {:?}", x.mem[0], z.mem[0], z.mem[1], reget_three[0], reget_three.slice()[1]); let mut _z = stackallocator.alloc_cell(1); } let mut halloc : HeapAllocator = HeapAllocator::{default_value: 0}; for _i in 1..10 { // heap test let mut x = halloc.alloc_cell(100000); x[0] = 4; let mut y = halloc.alloc_cell(110000); y[0] = 5; let mut z = halloc.alloc_cell(120000); z[0] = 6; halloc.free_cell(y); println!("x[0] {:?} x[9] {:?} y[0] {:?} z[0] {:?}", x[0], x[9], -999, z[0]); } } alloc-no-stdlib-2.0.4/src/bin/heap_alloc.rs000064400000000000000000000021021046102023000166010ustar 00000000000000use alloc_no_stdlib; use core; use alloc_no_stdlib::{SliceWrapper, SliceWrapperMut}; pub struct Rebox { b : Box<[T]>, } impl core::default::Default for Rebox { fn default() -> Self { let v : Vec = Vec::new(); let b = v.into_boxed_slice(); return Rebox::{b : b}; } } define_index_ops_mut!(T, Rebox); impl alloc_no_stdlib::SliceWrapper for Rebox { fn slice(&self) -> & [T] { return &*self.b } } impl alloc_no_stdlib::SliceWrapperMut for Rebox { fn slice_mut(&mut self) -> &mut [T] { return &mut*self.b } } pub struct HeapAllocator{ pub default_value : T, } impl alloc_no_stdlib::Allocator for HeapAllocator { type AllocatedMemory = Rebox; fn alloc_cell(self : &mut HeapAllocator, len : usize) -> Rebox { let v : Vec = vec![self.default_value.clone();len]; let b = v.into_boxed_slice(); return Rebox::{b : b}; } fn free_cell(self : &mut HeapAllocator, _data : Rebox) { } } alloc-no-stdlib-2.0.4/src/bin/tests.rs000075500000000000000000000032341046102023000156660ustar 00000000000000#![allow(unused_imports)] #[cfg(test)] extern crate core; use alloc_no_stdlib::Allocator; use super::HeapAllocator; #[cfg(feature="stdlib")] use alloc_no_stdlib::HeapAlloc; #[cfg(all(feature="unsafe", feature="stdlib"))] use alloc_no_stdlib::HeapAllocUninitialized; #[test] fn heap_test() { let mut halloc : HeapAllocator = HeapAllocator::{default_value: 0}; for _i in 1..10 { // heap test let mut x = halloc.alloc_cell(100000); x[0] = 4; let mut y = halloc.alloc_cell(110000); y[0] = 5; let mut z = halloc.alloc_cell(120000); z[0] = 6; assert_eq!(y[0], 5); halloc.free_cell(y); assert_eq!(x[0], 4); assert_eq!(x[9], 0); assert_eq!(z[0], 6); } } #[cfg(all(feature="unsafe", feature="stdlib"))] #[test] fn std_unsafe_heap_test() { let mut halloc = unsafe{HeapAllocUninitialized::::new()}; for _i in 1..10 { // heap test let mut x = halloc.alloc_cell(100000); x[0] = 4; let mut y = halloc.alloc_cell(110000); y[0] = 5; let mut z = halloc.alloc_cell(120000); z[0] = 6; assert_eq!(y[0], 5); halloc.free_cell(y); assert_eq!(x[0], 4); assert_eq!(x[9], 0); assert_eq!(z[0], 6); } } #[cfg(feature="stdlib")] #[test] fn std_heap_test() { let mut halloc = HeapAlloc::::new(0); for _i in 1..10 { // heap test let mut x = halloc.alloc_cell(100000); x[0] = 4; let mut y = halloc.alloc_cell(110000); y[0] = 5; let mut z = halloc.alloc_cell(120000); z[0] = 6; assert_eq!(y[0], 5); halloc.free_cell(y); assert_eq!(x[0], 4); assert_eq!(x[9], 0); assert_eq!(z[0], 6); } } alloc-no-stdlib-2.0.4/src/init.rs000064400000000000000000000231071046102023000147150ustar 00000000000000#[macro_export] macro_rules! static_array { (@accum (0, $($_ignored:expr),*) -> ($($body:tt)*)) => {static_array!(@as_expr [$($body)*])}; (@accum (1, $($expr:expr),*) -> ($($body:tt)*)) => {static_array!(@accum (0, $($expr),*) -> ($($body)* $($expr,)*))}; (@accum (2, $($expr:expr),*) -> ($($body:tt)*)) => {static_array!(@accum (0, $($expr),*) -> ($($body)* $($expr,)* $($expr,)*))}; (@accum (4, $($expr:expr),*) -> ($($body:tt)*)) => {static_array!(@accum (2, $($expr,)* $($expr),*) -> ($($body)*))}; (@accum (8, $($expr:expr),*) -> ($($body:tt)*)) => {static_array!(@accum (4, $($expr,)* $($expr),*) -> ($($body)*))}; (@accum (16, $($expr:expr),*) -> ($($body:tt)*)) => {static_array!(@accum (8, $($expr,)* $($expr),*) -> ($($body)*))}; (@accum (32, $($expr:expr),*) -> ($($body:tt)*)) => {static_array!(@accum (16, $($expr,)* $($expr),*) -> ($($body)*))}; (@accum (64, $($expr:expr),*) -> ($($body:tt)*)) => {static_array!(@accum (32, $($expr,)* $($expr),*) -> ($($body)*))}; (@accum (128, $($expr:expr),*) -> ($($body:tt)*)) => {static_array!(@accum (64, $($expr,)* $($expr),*) -> ($($body)*))}; (@accum (256, $($expr:expr),*) -> ($($body:tt)*)) => {static_array!(@accum (128, $($expr,)* $($expr),*) -> ($($body)*))}; (@accum (512, $($expr:expr),*) -> ($($body:tt)*)) => {static_array!(@accum (256, $($expr,)* $($expr),*) -> ($($body)*))}; (@accum (1024, $($expr:expr),*) -> ($($body:tt)*)) => {static_array!(@accum (512, $($expr,)* $($expr),*) -> ($($body)*))}; (@accum (2048, $($expr:expr),*) -> ($($body:tt)*)) => {static_array!(@accum (1024, $($expr,)* $($expr),*) -> ($($body)*))}; (@accum (4096, $($expr:expr),*) -> ($($body:tt)*)) => {static_array!(@accum (2048, $($expr,)* $($expr),*) -> ($($body)*))}; (@accum (8192, $($expr:expr),*) -> ($($body:tt)*)) => {static_array!(@accum (4096, $($expr,)* $($expr),*) -> ($($body)*))}; (@as_expr $expr:expr) => {$expr}; ($expr:expr; $n:tt) => { static_array!(@accum ($n, $expr) -> ()) }; } #[macro_export] macro_rules! define_stack_allocator_traits( ($name : ident, global) => { impl<'a, T: 'a> Default for $name<'a, T> { fn default() -> Self { return $name::<'a, T>{freelist : &mut[],}; } } define_stack_allocator_traits!($name, generic); }; ($name : ident, $freelist_size : tt, stack) => { impl<'a, T: 'a> Default for $name<'a, T> { fn default() -> Self { return $name::<'a, T>{freelist : static_array!(&mut[]; $freelist_size)}; } } define_stack_allocator_traits!($name, generic); }; ($name : ident, heap) => { impl<'a, T: 'a> Default for $name<'a, T> { fn default() -> Self { let v : Vec<&mut [T]> = Vec::new(); let b = v.into_boxed_slice(); return $name::<'a, T>{freelist : b}; } } define_stack_allocator_traits!($name, generic); }; ($name : ident, $freelist_size : tt, malloc) => { define_stack_allocator_traits!($name, calloc); }; ($name : ident, $freelist_size : tt, calloc) => { impl<'a, T: 'a> Default for $name<'a, T> { fn default() -> Self { return $name::<'a, T>{freelist : static_array!(&mut[]; $freelist_size)}; } } define_stack_allocator_traits!($name, generic); }; ($name : ident, generic) => { impl<'a, T: 'a> SliceWrapper<&'a mut[T]> for $name<'a, T> { fn slice(& self) -> & [&'a mut[T]] { return & self.freelist; } } impl<'a, T: 'a> SliceWrapperMut<&'a mut [T]> for $name<'a, T> { fn slice_mut(& mut self) ->&mut [&'a mut [T]] { return &mut self.freelist; } } impl<'a, T: 'a> ops::Index for $name<'a, T> { type Output = [T]; fn index<'b> (&'b self, _index : usize) -> &'b [T] { return &self.freelist[_index]; } } impl<'a, T: 'a> ops::IndexMut for $name<'a, T> { fn index_mut<'b>(&'b mut self, _index : usize) -> &'b mut [T] { return &mut self.freelist[_index]; } } }; ); #[macro_export] macro_rules! declare_stack_allocator_struct( (@as_expr $expr : expr) => {$expr}; (@new_method $name : ident, $freelist_size : tt) => { impl<'a, T: 'a> $name<'a, T> { fn new_allocator(global_buffer : &'a mut [T], initializer : fn(&mut[T])) -> StackAllocator<'a, T, $name<'a, T> > { let mut retval = StackAllocator:: > { nop : &mut [], system_resources : $name::::default(), free_list_start : declare_stack_allocator_struct!(@as_expr $freelist_size), free_list_overflow_count : 0, initialize : initializer, }; retval.free_cell(AllocatedStackMemory::{mem:global_buffer}); return retval; } } }; (@new_calloc_method $name : ident, $freelist_size : tt) => { impl<'a, T: 'a> $name<'a, T> { fn new_allocator(mut global_buffer : &'a mut [T], initializer : fn(&mut[T])) -> StackAllocator<'a, T, $name<'a, T> > { let mut retval = StackAllocator:: > { nop : &mut [], system_resources : $name::::default(), free_list_start : declare_stack_allocator_struct!(@as_expr $freelist_size), free_list_overflow_count : 0, initialize : initializer, }; retval.free_cell(AllocatedStackMemory::{mem:core::mem::replace(&mut global_buffer, &mut[])}); return retval; } } }; ($name :ident, $freelist_size : tt, malloc) => { declare_stack_allocator_struct!($name, $freelist_size, calloc); }; ($name :ident, $freelist_size : tt, calloc) => { struct $name<'a, T : 'a> { freelist : [&'a mut [T]; declare_stack_allocator_struct!(@as_expr $freelist_size)], } define_stack_allocator_traits!($name, $freelist_size, calloc); declare_stack_allocator_struct!( @new_calloc_method $name, $freelist_size); }; ($name :ident, $freelist_size : tt, stack) => { struct $name<'a, T : 'a> { freelist : [&'a mut [T];declare_stack_allocator_struct!(@as_expr $freelist_size)], // can't borrow here: make it on stack-- heap : core::cell::RefCell<[T; $heap_size]> } define_stack_allocator_traits!($name, $freelist_size, stack); declare_stack_allocator_struct!( @new_method $name, $freelist_size); }; ($name :ident, $freelist_size : expr, global) => { struct $name <'a, T: 'a> {freelist : &'a mut [&'a mut [T]]} define_stack_allocator_traits!($name, global); impl<'a, T: 'a> $name<'a, T> { fn new_allocator(initializer : fn (&mut[T])) -> StackAllocator<'a, T, $name<'a, T> > { return StackAllocator:: > { nop : &mut [], system_resources : $name::::default(), free_list_start : 0, free_list_overflow_count : 0, initialize : initializer, }; } } }; ); #[macro_export] macro_rules! bind_global_buffers_to_allocator( ($allocator : expr, $buffer : ident, $T : ty) => { $allocator.free_list_start = $buffer::FREELIST.len(); $allocator.system_resources.freelist = &mut $buffer::FREELIST; $allocator.free_cell(AllocatedStackMemory::<$T>{mem:&mut $buffer::HEAP}); }; ); #[macro_export] macro_rules! define_allocator_memory_pool( (@as_expr $expr:expr) => {$expr}; ($freelist_size : tt, $T : ty, [0; $heap_size : expr], calloc) => { alloc_no_stdlib::CallocBackingStore::<$T>::new($heap_size, alloc_no_stdlib::AllocatorC::Calloc(calloc), free, true); }; ($freelist_size : tt, $T : ty, [0; $heap_size : expr], calloc_no_free) => { alloc_no_stdlib::CallocBackingStore::<$T>::new($heap_size, alloc_no_stdlib::AllocatorC::Calloc(calloc), free, false); }; ($freelist_size : tt, $T : ty, [0; $heap_size : expr], malloc) => { alloc_no_stdlib::CallocBackingStore::<$T>::new($heap_size, alloc_no_stdlib::AllocatorC::Malloc(malloc), free, true); }; ($freelist_size : tt, $T : ty, [0; $heap_size : expr], malloc_no_free) => { alloc_no_stdlib::CallocBackingStore::<$T>::new($heap_size, alloc_no_stdlib::AllocatorC::Malloc(malloc), free, false); }; ($freelist_size : tt, $T : ty, [$default_value : expr; $heap_size : expr], heap) => { (vec![$default_value; $heap_size]).into_boxed_slice(); }; ($freelist_size : tt, $T : ty, [$default_value : expr; $heap_size : expr], stack) => { [$default_value; $heap_size]; }; ($freelist_size : tt, $T : ty, [$default_value : expr; $heap_size : expr], global, $name : ident) => { pub mod $name { pub static mut FREELIST : [&'static mut [$T]; define_allocator_memory_pool!(@as_expr $freelist_size)] = static_array!(&mut[]; $freelist_size); pub static mut HEAP : [$T; $heap_size] = [$default_value; $heap_size]; } }; ); alloc-no-stdlib-2.0.4/src/lib.rs000075500000000000000000000051251046102023000145230ustar 00000000000000#![no_std] #[macro_use] mod allocated_memory; mod stack_allocator; mod allocated_stack_memory; #[macro_use] pub mod init; pub use allocated_memory::SliceWrapper; pub use allocated_memory::SliceWrapperMut; pub use allocated_memory::AllocatedSlice; pub use allocated_stack_memory::AllocatedStackMemory; pub use stack_allocator::Allocator; pub use stack_allocator::StackAllocator; use core::default::Default; pub fn bzero (data : &mut [T]) { for iter in data.iter_mut() { *iter = T::default(); } } pub fn uninitialized (_data : &mut[T]) {} #[derive(Debug)] pub struct CallocBackingStore<'a, T : 'a> { pub raw_data : *mut u8, pub data : &'a mut[T], free : unsafe extern "C" fn(*mut u8), } pub enum AllocatorC { Calloc(unsafe extern "C" fn(usize, usize) -> *mut u8), Malloc(unsafe extern "C" fn(usize) -> *mut u8), Custom(fn(usize) -> *mut u8), } impl<'a, T : 'a> CallocBackingStore<'a, T> { pub unsafe fn new(num_elements : usize, alloc : AllocatorC, free : unsafe extern "C" fn (*mut u8), should_free : bool) -> Self{ let retval : *mut u8 = if num_elements == 0 {core::ptr::null_mut()} else { match alloc { AllocatorC::Calloc(calloc) => calloc(num_elements, core::mem::size_of::()), AllocatorC::Malloc(malloc) => malloc(num_elements *core::mem::size_of::()), AllocatorC::Custom(malloc) => malloc(num_elements *core::mem::size_of::()), } }; if num_elements == 0 || retval.is_null() { return CallocBackingStore::<'a, T>{ raw_data : core::ptr::null_mut(), data : &mut[], free : free, } } let raw_data : *mut T = core::mem::transmute(retval); if should_free { return CallocBackingStore::<'a, T>{ raw_data : retval, data : core::slice::from_raw_parts_mut(raw_data, num_elements), free : free, }; } else { let null_ptr : *const u8 = core::ptr::null(); return CallocBackingStore::<'a, T>{ raw_data : core::mem::transmute(null_ptr),//retval, data : core::slice::from_raw_parts_mut(raw_data, num_elements), free : free, }; } } } impl<'a, T:'a> Drop for CallocBackingStore<'a, T> { fn drop(self :&mut Self) { // core::mem::forget(core::mem::replace(self.data, &mut[])); core::mem::forget(core::mem::replace(&mut self.data, &mut[])); if !self.raw_data.is_null() { let local_free = self.free; unsafe {(local_free)(self.raw_data)}; } } } alloc-no-stdlib-2.0.4/src/stack_allocator.rs000064400000000000000000000101231046102023000171110ustar 00000000000000extern crate core; use super::allocated_memory; use super::allocated_stack_memory::AllocatedStackMemory; use super::SliceWrapper; pub trait Allocator { type AllocatedMemory : allocated_memory::AllocatedSlice; fn alloc_cell(&mut self, len : usize) -> Self::AllocatedMemory; fn free_cell(&mut self, data : Self::AllocatedMemory); } pub struct StackAllocator<'a, T :'a, U : allocated_memory::AllocatedSlice<&'a mut [T]>> { pub nop : &'a mut [T], pub system_resources : U, pub free_list_start : usize, pub free_list_overflow_count : usize, pub initialize : fn(&mut[T]), } impl <'a, T : 'a, U : allocated_memory::AllocatedSlice<&'a mut[T]> > StackAllocator <'a, T, U> { fn clear_if_necessary(self : &Self, index : usize, data : AllocatedStackMemory<'a, T>) -> AllocatedStackMemory<'a, T> { if index + 1 != self.system_resources.slice().len() { let fnp = self.initialize; fnp(data.mem); } return data; } } impl<'a, T : 'a, U : allocated_memory::AllocatedSlice<&'a mut[T]> > Allocator for StackAllocator <'a, T, U> { type AllocatedMemory = AllocatedStackMemory<'a, T>; fn alloc_cell(self : &mut StackAllocator<'a, T, U>, len : usize) -> AllocatedStackMemory<'a, T> { if len == 0 { return AllocatedStackMemory::<'a, T>::default(); } let mut index : usize = self.free_list_start; let mut found : bool = false; for free_resource in self.system_resources.slice()[self.free_list_start..].iter() { if free_resource.len() >= len { found = true; break; } index += 1; } if !found { panic!("OOM"); } let available_slice = core::mem::replace(&mut self.system_resources.slice_mut()[index], &mut[]); if available_slice.len() == len || (available_slice.len() < len + 32 && index + 1 != self.system_resources.slice().len()) { // we don't want really small wasted slices // we must assign free_list_start if index != self.free_list_start { assert!(index > self.free_list_start); let farthest_free_list = core::mem::replace( &mut self.system_resources.slice_mut()[self.free_list_start], &mut []); let _ = core::mem::replace(&mut self.system_resources.slice_mut()[index], farthest_free_list); } self.free_list_start += 1; return self.clear_if_necessary(index, AllocatedStackMemory::<'a, T>{mem:available_slice}); } else { // the memory allocated was not the entire range of items. Split and move on let (retval, return_to_sender) = available_slice.split_at_mut(len); let _ = core::mem::replace(&mut self.system_resources.slice_mut()[index], return_to_sender); return self.clear_if_necessary(index, AllocatedStackMemory::<'a, T>{mem:retval}); } } fn free_cell(self : &mut StackAllocator<'a, T, U>, val : AllocatedStackMemory<'a, T>) { if val.slice().len() == 0 { return; } if self.free_list_start > 0 { self.free_list_start -=1; let _ = core::mem::replace(&mut self.system_resources.slice_mut()[self.free_list_start], val.mem); } else { for _i in 0..3 { self.free_list_overflow_count += 1; self.free_list_overflow_count %= self.system_resources.slice().len(); if self.system_resources.slice()[self.free_list_overflow_count].len() < val.mem.len() { let _ = core::mem::replace(&mut self.system_resources.slice_mut()[self.free_list_overflow_count], val.mem); return; } } } } } alloc-no-stdlib-2.0.4/src/tests.rs000064400000000000000000000040251046102023000151120ustar 00000000000000#![allow(unused_imports)] #![allow(dead_code)] #[cfg(test)] extern crate core; use core::ops; use super::{Allocator, SliceWrapperMut, SliceWrapper, StackAllocator, AllocatedStackMemory, CallocBackingStore}; struct StackAllocatedFreelist4<'a, T : 'a> { freelist : [&'a mut [T]; 4], } impl<'a, T: 'a> SliceWrapper<&'a mut[T]> for StackAllocatedFreelist4<'a, T> { fn slice(& self) -> & [&'a mut[T]] { return & self.freelist; } } impl<'a, T: 'a> SliceWrapperMut<&'a mut [T]> for StackAllocatedFreelist4<'a, T> { fn slice_mut(& mut self) ->&mut [&'a mut [T]] { return &mut self.freelist; } } impl<'a, T: 'a> ops::Index for StackAllocatedFreelist4<'a, T> { type Output = [T]; fn index<'b> (&'b self, _index : usize) -> &'b [T] { return &self.freelist[_index]; } } impl<'a, T: 'a> ops::IndexMut for StackAllocatedFreelist4<'a, T> { fn index_mut<'b>(&'b mut self, _index : usize) -> &'b mut [T] { return &mut self.freelist[_index]; } } #[test] fn integration_test() { let mut global_buffer : [u8; 65536] = [0; 65536]; let mut ags = StackAllocator:: > { nop : &mut [], system_resources : StackAllocatedFreelist4:: { freelist : [&mut[],&mut[],&mut[],&mut[],], }, free_list_start : 4, free_list_overflow_count : 0, initializer : bzero, }; ags.free_cell(AllocatedStackMemory::{mem:&mut global_buffer}); { let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; let mut y = ags.alloc_cell(4); y[0] = 5; ags.free_cell(y); let mut three = ags.alloc_cell(3); three[0] = 6; ags.free_cell(three); let mut z = ags.alloc_cell(4); z.slice_mut()[1] = 8; let mut reget_three = ags.alloc_cell(4); reget_three.slice_mut()[1] = 9; //y.mem[0] = 6; // <-- this is an error (use after free) assert_eq!(x[0], 4); assert_eq!(z[0], 6); assert_eq!(z[1], 8); assert_eq!(reget_three[0], 0); assert_eq!(reget_three[1], 9); let mut _z = ags.alloc_cell(1); } } alloc-no-stdlib-2.0.4/tests/lib.rs000075500000000000000000000237441046102023000151050ustar 00000000000000#![allow(unused_imports)] #![allow(dead_code)] //#![feature(trace_macros)] #[cfg(test)] #[macro_use] extern crate alloc_no_stdlib; extern crate core; use core::ops; use alloc_no_stdlib::{Allocator, SliceWrapperMut, SliceWrapper, StackAllocator, AllocatedStackMemory, uninitialized, bzero}; declare_stack_allocator_struct!(CallocAllocatedFreelist4096, 4096, calloc); declare_stack_allocator_struct!(StackAllocatedFreelist4, 4, stack); declare_stack_allocator_struct!(StackAllocatedFreelist8, 8, stack); declare_stack_allocator_struct!(GlobalAllocatedFreelist, 16, global); //trace_macros!(true); define_allocator_memory_pool!(16, u8, [0; 1024 * 1024 * 100], global, global_buffer); define_allocator_memory_pool!(16, u8, [0; 1024 * 1024 * 100], global, global_buffer2); extern { fn calloc(n_elem : usize, el_size : usize) -> *mut u8; fn free(item : *mut u8); } #[test] fn uninitialized_stack_pool_test() { { let mut stack_global_buffer = define_allocator_memory_pool!(4, u8, [0; 65536], stack); let mut ags = StackAllocatedFreelist4::::new_allocator(&mut stack_global_buffer, uninitialized); { let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; let mut y = ags.alloc_cell(4); y[0] = 5; ags.free_cell(y); let mut three = ags.alloc_cell(3); three[0] = 6; ags.free_cell(three); let mut z = ags.alloc_cell(4); z.slice_mut()[1] = 8; let mut reget_three = ags.alloc_cell(4); reget_three.slice_mut()[1] = 9; //y.mem[0] = 6; // <-- this is an error (use after free) assert_eq!(x[0], 4); assert_eq!(z[0], 6); assert_eq!(z[1], 8); assert_eq!(reget_three[0], 0); assert_eq!(reget_three[1], 9); let mut _z = ags.alloc_cell(1); } } } #[test] fn uninitialized_stack_pool_free_null() { let mut stack_global_buffer = define_allocator_memory_pool!(8, u8, [0; 256 - 8], stack); let mut ags = StackAllocatedFreelist8::::new_allocator(&mut stack_global_buffer, uninitialized); { let s = ags.alloc_cell(0); //u.slice_mut()[0] = 4; let t = ags.alloc_cell(0); //u.slice_mut()[0] = 4; let u = ags.alloc_cell(0); //u.slice_mut()[0] = 4; let v = ags.alloc_cell(0); //v.slice_mut()[0] = 4; let ss = ags.alloc_cell(0); //u.slice_mut()[0] = 4; let tt = ags.alloc_cell(0); //u.slice_mut()[0] = 4; let uu = ags.alloc_cell(0); //u.slice_mut()[0] = 4; let vv = ags.alloc_cell(0); //v.slice_mut()[0] = 4; let mut w = ags.alloc_cell(31); w.slice_mut()[30] = 4; let mut x = ags.alloc_cell(31); x.slice_mut()[30] = 4; let mut y = ags.alloc_cell(31); y.slice_mut()[30] = 4; let mut z = ags.alloc_cell(31); z.slice_mut()[30] = 4; let mut zz = ags.alloc_cell(31); zz.slice_mut()[30] = 4; let mut xx = ags.alloc_cell(31); xx.slice_mut()[30] = 4; let mut yy = ags.alloc_cell(31); yy.slice_mut()[30] = 4; let mut ww = ags.alloc_cell(31); ww.slice_mut()[30] = 4; ags.free_cell(y); ags.free_cell(x); ags.free_cell(z); ags.free_cell(zz); ags.free_cell(xx); ags.free_cell(yy); ags.free_cell(ww); ags.free_cell(v); ags.free_cell(u); ags.free_cell(s); ags.free_cell(t); ags.free_cell(w); ags.free_cell(vv); ags.free_cell(uu); ags.free_cell(ss); ags.free_cell(tt); let mut a = ags.alloc_cell(31); a.slice_mut()[30] = 4; let mut b = ags.alloc_cell(31); b.slice_mut()[30] = 4; let mut c = ags.alloc_cell(31); c.slice_mut()[30] = 4; let mut d = ags.alloc_cell(31); d.slice_mut()[30] = 4; let mut e = ags.alloc_cell(31); e.slice_mut()[30] = 4; let mut f = ags.alloc_cell(31); f.slice_mut()[30] = 4; let mut g = ags.alloc_cell(31); g.slice_mut()[30] = 4; let mut h = ags.alloc_cell(31); h.slice_mut()[30] = 4; } } #[test] fn uninitialized_calloc_pool_test() { { let mut calloc_global_buffer = unsafe{define_allocator_memory_pool!(4096, u8, [0; 200 * 1024 * 1024], calloc)}; let mut ags = CallocAllocatedFreelist4096::::new_allocator(&mut calloc_global_buffer.data, uninitialized); { let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; let mut y = ags.alloc_cell(4); y[0] = 5; ags.free_cell(y); let mut three = ags.alloc_cell(3); three[0] = 6; ags.free_cell(three); let mut z = ags.alloc_cell(4); z.slice_mut()[1] = 8; let mut reget_three = ags.alloc_cell(4); reget_three.slice_mut()[1] = 9; //y.mem[0] = 6; // <-- this is an error (use after free) assert_eq!(x[0], 4); assert_eq!(z[0], 6); assert_eq!(z[1], 8); assert_eq!(reget_three[0], 0); assert_eq!(reget_three[1], 9); let mut _z = ags.alloc_cell(1); } println!("{:?}", ags.free_list_start); } } #[test] fn uninitialized_global_pool_test() { { let mut ags = GlobalAllocatedFreelist::::new_allocator(uninitialized); unsafe { bind_global_buffers_to_allocator!(ags, global_buffer, u8); } { let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; let mut y = ags.alloc_cell(4); y[0] = 5; ags.free_cell(y); let mut three = ags.alloc_cell(3); three[0] = 6; ags.free_cell(three); let mut z = ags.alloc_cell(4); z.slice_mut()[1] = 8; let mut reget_three = ags.alloc_cell(4); reget_three.slice_mut()[1] = 9; //y.mem[0] = 6; // <-- this is an error (use after free) assert_eq!(x[0], 4); assert_eq!(z[0], 6); assert_eq!(z[1], 8); assert_eq!(reget_three[0], 0); assert_eq!(reget_three[1], 9); let mut _z = ags.alloc_cell(1); } } } #[test] fn stack_pool_test() { { let mut stack_global_buffer = define_allocator_memory_pool!(4, u8, [0; 65536], stack); let mut ags = StackAllocatedFreelist4::::new_allocator(&mut stack_global_buffer, bzero); { let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; let mut y = ags.alloc_cell(4); y[0] = 5; ags.free_cell(y); let mut three = ags.alloc_cell(3); three[0] = 6; ags.free_cell(three); let mut z = ags.alloc_cell(4); z.slice_mut()[1] = 8; let mut reget_three = ags.alloc_cell(4); reget_three.slice_mut()[1] = 9; //y.mem[0] = 6; // <-- this is an error (use after free) assert_eq!(x[0], 4); assert_eq!(z[0], 0); assert_eq!(z[1], 8); assert_eq!(reget_three[0], 0); assert_eq!(reget_three[1], 9); let mut _z = ags.alloc_cell(1); } } } #[test] fn stack_pool_free_null() { let mut stack_global_buffer = define_allocator_memory_pool!(8, u8, [0; 256 - 8], stack); let mut ags = StackAllocatedFreelist8::::new_allocator(&mut stack_global_buffer, bzero); { let s = ags.alloc_cell(0); //u.slice_mut()[0] = 4; let t = ags.alloc_cell(0); //u.slice_mut()[0] = 4; let u = ags.alloc_cell(0); //u.slice_mut()[0] = 4; let v = ags.alloc_cell(0); //v.slice_mut()[0] = 4; let ss = ags.alloc_cell(0); //u.slice_mut()[0] = 4; let tt = ags.alloc_cell(0); //u.slice_mut()[0] = 4; let uu = ags.alloc_cell(0); //u.slice_mut()[0] = 4; let vv = ags.alloc_cell(0); //v.slice_mut()[0] = 4; let mut w = ags.alloc_cell(31); w.slice_mut()[30] = 4; let mut x = ags.alloc_cell(31); x.slice_mut()[30] = 4; let mut y = ags.alloc_cell(31); y.slice_mut()[30] = 4; let mut z = ags.alloc_cell(31); z.slice_mut()[30] = 4; let mut zz = ags.alloc_cell(31); zz.slice_mut()[30] = 4; let mut xx = ags.alloc_cell(31); xx.slice_mut()[30] = 4; let mut yy = ags.alloc_cell(31); yy.slice_mut()[30] = 4; let mut ww = ags.alloc_cell(31); ww.slice_mut()[30] = 4; ags.free_cell(y); ags.free_cell(x); ags.free_cell(z); ags.free_cell(zz); ags.free_cell(xx); ags.free_cell(yy); ags.free_cell(ww); ags.free_cell(v); ags.free_cell(u); ags.free_cell(s); ags.free_cell(t); ags.free_cell(w); ags.free_cell(vv); ags.free_cell(uu); ags.free_cell(ss); ags.free_cell(tt); let mut a = ags.alloc_cell(31); a.slice_mut()[30] = 4; let mut b = ags.alloc_cell(31); b.slice_mut()[30] = 4; let mut c = ags.alloc_cell(31); c.slice_mut()[30] = 4; let mut d = ags.alloc_cell(31); d.slice_mut()[30] = 4; let mut e = ags.alloc_cell(31); e.slice_mut()[30] = 4; let mut f = ags.alloc_cell(31); f.slice_mut()[30] = 4; let mut g = ags.alloc_cell(31); g.slice_mut()[30] = 4; let mut h = ags.alloc_cell(31); h.slice_mut()[30] = 4; } } #[test] fn calloc_pool_test() { { let mut calloc_global_buffer = unsafe {define_allocator_memory_pool!(4096, u8, [0; 200 * 1024 * 1024], calloc)}; let mut ags = CallocAllocatedFreelist4096::::new_allocator(&mut calloc_global_buffer.data, bzero); { let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; let mut y = ags.alloc_cell(4); y[0] = 5; ags.free_cell(y); let mut three = ags.alloc_cell(3); three[0] = 6; ags.free_cell(three); let mut z = ags.alloc_cell(4); z.slice_mut()[1] = 8; let mut reget_three = ags.alloc_cell(4); reget_three.slice_mut()[1] = 9; //y.mem[0] = 6; // <-- this is an error (use after free) assert_eq!(x[0], 4); assert_eq!(z[0], 0); assert_eq!(z[1], 8); assert_eq!(reget_three[0], 0); assert_eq!(reget_three[1], 9); let mut _z = ags.alloc_cell(1); } } } #[test] fn global_pool_test() { { let mut ags = GlobalAllocatedFreelist::::new_allocator(bzero); unsafe { bind_global_buffers_to_allocator!(ags, global_buffer2, u8); } { let mut x = ags.alloc_cell(9999); x.slice_mut()[0] = 4; let mut y = ags.alloc_cell(4); y[0] = 5; ags.free_cell(y); let mut three = ags.alloc_cell(3); three[0] = 6; ags.free_cell(three); let mut z = ags.alloc_cell(4); z.slice_mut()[1] = 8; let mut reget_three = ags.alloc_cell(4); reget_three.slice_mut()[1] = 9; //y.mem[0] = 6; // <-- this is an error (use after free) assert_eq!(x[0], 4); assert_eq!(z[0], 0); assert_eq!(z[1], 8); assert_eq!(reget_three[0], 0); assert_eq!(reget_three[1], 9); let mut _z = ags.alloc_cell(1); } } }