-
Notifications
You must be signed in to change notification settings - Fork 11
Description
We want to minimize these throughout the library, for security reasons if nothing else.
An example of a bad pattern accepting a String
or a Vec<u8>
as a parameter to a function. Instead, one can always coerce into &str
or &[u8]
with a simple &
from a String
or Vec<u8>
, so I've found the minimizing application code pattern to be accepting parameters as &str
and &[u8]
(and &Matter
etc). Values returned from functions are typically then the non-borrowed, juiced up version of the types. Here is a concrete example:
Good:
fn trim(input: &[u8], length: usize) -> Vec<u8> {
input[..length].to_vec()
}
fn string_to_vec(input: &str) -> Vec<u8> {
input.as_bytes().to_vec()
}
// example usage
fn exercise() {
let v = trim(&string_to_vec("stuff"), 3);
}
Bad:
fn foo(input: Vec<u8>) -> Vec<u8> {
input[..len]
}
fn foo(input: String) -> Vec<u8> {
input
}
// example usage, notice how we need another .to_string() in the
// calling code, and we lose the & on the vec param
fn exercise() {
let v = trim(string_to_vec("stuff".to_string()), 3);
}
In addition to adding complexity to the application (which we must aim to minimize), the longer one can leave variables as borrowed primitive entities, the more one opens up the door to making efficiency gains from using data in place. It's also less zeroing memory to worry about, as there will be less copies of sensitive information in memory in general.