summaryrefslogtreecommitdiffstats
path: root/rust/vendor/alloc-stdlib/README.md
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--rust/vendor/alloc-stdlib/README.md205
1 files changed, 205 insertions, 0 deletions
diff --git a/rust/vendor/alloc-stdlib/README.md b/rust/vendor/alloc-stdlib/README.md
new file mode 100644
index 0000000..f40bd29
--- /dev/null
+++ b/rust/vendor/alloc-stdlib/README.md
@@ -0,0 +1,205 @@
+# Framework for allocating memory in #![no_std] modules.
+
+[![crates.io](http://meritbadge.herokuapp.com/alloc-no-stdlib)](https://crates.io/crates/alloc-no-stdlib)
+[![Build Status](https://travis-ci.org/dropbox/rust-alloc-no-stdlib.svg?branch=master)](https://travis-ci.org/dropbox/rust-alloc-no-stdlib)
+
+
+## Requirements
+ * Rust 1.6
+
+## Documentation
+Currently there is no standard way to allocate memory from within a module that is no_std.
+This provides a mechanism to allocate memory using the stdlib-independent
+memory allocation system described by rust-alloc-no-stdlib
+describe a memory allocation that can be satisfied entirely on
+the stack, by unsafely linking to calloc, or by unsafely referencing a mutable global variable.
+This library currently will leak memory if free_cell isn't specifically invoked on memory.
+
+However, if linked by a library that actually can depend on the stdlib then that library
+can simply pass in a few allocators and use the standard Box allocation and will free automatically.
+
+This library should also make it possible to entirely jail a rust application that needs dynamic
+allocations by preallocating a maximum limit of data upfront using calloc and
+using seccomp to disallow future syscalls.
+
+## Usage
+
+There are 3 modes for allocating memory using the stdlib, each with advantages and disadvantages
+
+
+### On the heap
+This uses the standard Box facilities to allocate memory and assumeds a default constructor
+for the given type
+
+```rust
+let mut halloc = StandardAlloc::new(0);
+for _i in 1..10 { // heap test
+ let mut x = <StandardAlloc as Allocator<u8>>::alloc_cell(&mut halloc, 100000)
+ x[0] = 4;
+ let mut y = <StandardAlloc as Allocator<u8>>::alloc_cell(&mut halloc, 100000)
+ y[0] = 5;
+ let mut z = <StandardAlloc as Allocator<u8>>::alloc_cell(&mut halloc, 100000)
+ z[0] = 6;
+ assert_eq!(y[0], 5);
+ halloc.free_cell(y);
+ assert_eq!(x[0], 4);
+ assert_eq!(x[9], 0);
+ assert_eq!(z[0], 6);
+}
+```
+
+### On the heap
+This uses the standard Box facilities to allocate memory but assuming a default user-provided value
+
+```rust
+let mut halloc = HeapAlloc::<u8>::new(8);
+for _i in 1..10 { // heap test
+ let mut x = halloc.alloc_cell(100000);
+ x[0] = 4;
+ let mut y = halloc.alloc_cell(110000);
+ y[0] = 5;
+ let mut z = halloc.alloc_cell(120000);
+ z[0] = 6;
+ assert_eq!(y[0], 5);
+ halloc.free_cell(y);
+ assert_eq!(x[0], 4);
+ assert_eq!(x[9], 8);
+ assert_eq!(z[0], 6);
+}
+```
+
+
+### On the heap, but uninitialized
+This does allocate data every time it is requested, but it does not allocate the
+memory, so naturally it is unsafe. The caller must initialize the memory properly
+```rust
+let mut halloc = unsafe{HeapAllocUninitialized::<u8>::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::<u8>::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::<u8>::new_uninitialized_memory_pool(6 * 1024 * 1024)};
+let mut ags = HeapPrealloc::<u8>::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::<u8>::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::<u8>::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