mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
add tor allocator for rust
This commit is contained in:
committed by
Nick Mathewson
parent
d14a83f74f
commit
76bbdfbfa9
+10
-10
@@ -8,7 +8,7 @@ use std::ffi::CString;
|
||||
|
||||
use protover::*;
|
||||
use smartlist::*;
|
||||
use tor_allocate::allocate_string;
|
||||
use tor_allocate::allocate_and_copy_string;
|
||||
|
||||
/// Translate C enums to Rust Proto enums, using the integer value of the C
|
||||
/// enum to map to its associated Rust enum
|
||||
@@ -124,17 +124,17 @@ pub extern "C" fn protover_compute_vote(
|
||||
) -> *mut c_char {
|
||||
|
||||
if list.is_null() {
|
||||
let mut empty = String::new();
|
||||
return allocate_string(&mut empty);
|
||||
let empty = String::new();
|
||||
return allocate_and_copy_string(&empty);
|
||||
}
|
||||
|
||||
// Dereference of raw pointer requires an unsafe block. The pointer is
|
||||
// checked above to ensure it is not null.
|
||||
let data: Vec<String> = unsafe { (*list).get_list() };
|
||||
|
||||
let mut vote = compute_vote(data, threshold);
|
||||
let vote = compute_vote(data, threshold);
|
||||
|
||||
allocate_string(&mut vote)
|
||||
allocate_and_copy_string(&vote)
|
||||
}
|
||||
|
||||
/// Provide an interface for C to translate arguments and return types for
|
||||
@@ -162,10 +162,10 @@ pub extern "C" fn protover_compute_for_old_tor(
|
||||
) -> *mut c_char {
|
||||
// Not handling errors when unwrapping as the content is controlled
|
||||
// and is an empty string
|
||||
let mut empty = String::new();
|
||||
let empty = String::new();
|
||||
|
||||
if version.is_null() {
|
||||
return allocate_string(&mut empty);
|
||||
return allocate_and_copy_string(&empty);
|
||||
}
|
||||
|
||||
// Require an unsafe block to read the version from a C string. The pointer
|
||||
@@ -174,10 +174,10 @@ pub extern "C" fn protover_compute_for_old_tor(
|
||||
|
||||
let version = match c_str.to_str() {
|
||||
Ok(n) => n,
|
||||
Err(_) => return allocate_string(&mut empty),
|
||||
Err(_) => return allocate_and_copy_string(&empty),
|
||||
};
|
||||
|
||||
let mut supported = compute_for_old_tor(&version);
|
||||
let supported = compute_for_old_tor(&version);
|
||||
|
||||
allocate_string(&mut supported)
|
||||
allocate_and_copy_string(&supported)
|
||||
}
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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::*;
|
||||
@@ -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) };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user