diff options
author | Chelsea Holland Komlo <me@chelseakomlo.com> | 2017-10-14 23:05:31 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2017-10-27 10:02:08 -0400 |
commit | 76bbdfbfa9eca46b53d3ec5a44deafce51d2875a (patch) | |
tree | c98dda928f61621d324e889f29ecf31ab9e917cb /src/rust/tor_allocate | |
parent | d14a83f74fcbe5fae97d944ac8f7f8645e160d3a (diff) | |
download | tor-76bbdfbfa9eca46b53d3ec5a44deafce51d2875a.tar.gz tor-76bbdfbfa9eca46b53d3ec5a44deafce51d2875a.zip |
add tor allocator for rust
Diffstat (limited to 'src/rust/tor_allocate')
-rw-r--r-- | src/rust/tor_allocate/Cargo.toml | 13 | ||||
-rw-r--r-- | src/rust/tor_allocate/include.am | 13 | ||||
-rw-r--r-- | src/rust/tor_allocate/lib.rs | 12 | ||||
-rw-r--r-- | src/rust/tor_allocate/tor_allocate.rs | 90 |
4 files changed, 128 insertions, 0 deletions
diff --git a/src/rust/tor_allocate/Cargo.toml b/src/rust/tor_allocate/Cargo.toml new file mode 100644 index 0000000000..ceb08b78ab --- /dev/null +++ b/src/rust/tor_allocate/Cargo.toml @@ -0,0 +1,13 @@ +[package] +authors = ["The Tor Project"] +version = "0.0.1" +name = "tor_allocate" + +[dependencies] +libc = "0.2.22" + +[lib] +name = "tor_allocate" +path = "lib.rs" +crate_type = ["rlib", "staticlib"] + diff --git a/src/rust/tor_allocate/include.am b/src/rust/tor_allocate/include.am new file mode 100644 index 0000000000..9e770dbc05 --- /dev/null +++ b/src/rust/tor_allocate/include.am @@ -0,0 +1,13 @@ +EXTRA_DIST +=\ + src/rust/tor_allocate/Cargo.toml \ + src/rust/tor_allocate/lib.rs \ + src/rust/tor_allocate/tor_allocate.rs + +src/rust/target/release/@TOR_RUST_C_STRING_STATIC_NAME@: FORCE + ( cd "$(abs_top_srcdir)/src/rust/tor_allocate" ; \ + CARGO_TARGET_DIR="$(abs_top_builddir)/src/rust/target" \ + CARGO_HOME="$(abs_top_builddir)/src/rust" \ + $(CARGO) build --release --quiet $(CARGO_ONLINE) ) + +FORCE: + diff --git a/src/rust/tor_allocate/lib.rs b/src/rust/tor_allocate/lib.rs new file mode 100644 index 0000000000..81afd095f9 --- /dev/null +++ b/src/rust/tor_allocate/lib.rs @@ -0,0 +1,12 @@ +//! Allocation helper functions that allow data to be allocated in Rust +//! using tor's specified allocator. In doing so, this can be later freed +//! from C. +//! +//! This is currently a temporary solution, we will later use tor's allocator +//! by default for any allocation that occurs in Rust. However, as this will +//! stabalize in 2018, we can use this as a temporary measure. + +extern crate libc; + +mod tor_allocate; +pub use tor_allocate::*; diff --git a/src/rust/tor_allocate/tor_allocate.rs b/src/rust/tor_allocate/tor_allocate.rs new file mode 100644 index 0000000000..de1d13942e --- /dev/null +++ b/src/rust/tor_allocate/tor_allocate.rs @@ -0,0 +1,90 @@ +use libc::{c_char, c_void}; +use std::{ptr, slice}; + +#[cfg(not(test))] +extern "C" { + fn tor_malloc_ ( size: usize) -> *mut c_void; +} + +// Defined only for tests, used for testing purposes, so that we don't need +// to link to tor C files. Uses the system allocator +#[cfg(test)] +extern "C" fn tor_malloc_ ( size: usize) -> *mut c_void { + use libc::malloc; + unsafe { malloc(size) } +} + +/// Allocate memory using tor_malloc_ and copy an existing string into the +/// allocated buffer, returning a pointer that can later be called in C. +/// +/// # Inputs +/// +/// * `src`, a reference to a String that will be copied. +/// +/// # Returns +/// +/// A `String` that should be freed by tor_free in C +/// +pub fn allocate_and_copy_string(src: &String) -> *mut c_char { + let bytes = s.as_bytes(); + + let size = s.len(); + let size_with_null_byte = size + 1; + + let dest = unsafe { tor_malloc_(size_with_null_byte) as *mut u8 }; + + if dest.is_null() { + return dest as *mut c_char; + } + + unsafe { ptr::copy_nonoverlapping(bytes.as_ptr(), dest, size) }; + + // set the last byte as null, using the ability to index into a slice + // rather than doing pointer arithmatic + let slice = unsafe { slice::from_raw_parts_mut(dest, size_with_null_byte) }; + slice[size] = 0; // add a null terminator + + dest as *mut c_char +} + +#[cfg(test)] +mod test { + + #[test] + fn test_allocate_and_copy_string_with_empty() { + use std::ffi::CStr; + use libc::{free, c_void}; + + use tor_allocate::allocate_and_copy_string; + + let empty = String::new(); + let allocated_empty = allocate_and_copy_string(&empty); + + let allocated_empty_rust = unsafe { + CStr::from_ptr(allocated_empty).to_str().unwrap() + }; + + assert_eq!("", allocated_empty_rust); + + unsafe { free(allocated_empty as *mut c_void) }; + } + + #[test] + fn test_allocate_and_copy_string_with_not_empty_string() { + use std::ffi::CStr; + use libc::{free, c_void}; + + use tor_allocate::allocate_and_copy_string; + + let empty = String::from("foo bar biz"); + let allocated_empty = allocate_and_copy_string(&empty); + + let allocated_empty_rust = unsafe { + CStr::from_ptr(allocated_empty).to_str().unwrap() + }; + + assert_eq!("foo bar biz", allocated_empty_rust); + + unsafe { free(allocated_empty as *mut c_void) }; + } +} |