Skip to content

Commit

Permalink
Merge pull request #240 from elichai/zeroize
Browse files Browse the repository at this point in the history
Optionally implement Zeroize on ArrayVec/ArrayString
  • Loading branch information
bluss committed Jun 15, 2023
2 parents 4ab6d63 + 71200c0 commit 2cd12ef
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 2 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/ci.yml
Expand Up @@ -22,12 +22,13 @@ jobs:
experimental: false
- rust: stable
features:
bench: true
experimental: false
- rust: beta
features: serde
experimental: false
- rust: nightly
features: serde
features: serde, zeroize
experimental: false

steps:
Expand Down Expand Up @@ -57,4 +58,4 @@ jobs:
rustup override set nightly
cargo miri setup
- name: Test with Miri
run: cargo miri test
run: cargo miri test --all-features
5 changes: 5 additions & 0 deletions Cargo.toml
Expand Up @@ -19,6 +19,11 @@ version = "1.0"
optional = true
default-features = false

[dependencies.zeroize]
version = "1.4"
optional = true
default-features = false

[dev-dependencies.serde_test]
version = "1.0"

Expand Down
24 changes: 24 additions & 0 deletions src/array_string.rs
Expand Up @@ -647,3 +647,27 @@ impl<'a, const CAP: usize> TryFrom<fmt::Arguments<'a>> for ArrayString<CAP>
Ok(v)
}
}

#[cfg(feature = "zeroize")]
/// "Best efforts" zeroing of the `ArrayString`'s buffer when the `zeroize` feature is enabled.
///
/// The length is set to 0, and the buffer is dropped and zeroized.
/// Cannot ensure that previous moves of the `ArrayString` did not leave values on the stack.
///
/// ```
/// use arrayvec::ArrayString;
/// use zeroize::Zeroize;
/// let mut string = ArrayString::<6>::from("foobar").unwrap();
/// string.zeroize();
/// assert_eq!(string.len(), 0);
/// unsafe { string.set_len(string.capacity()) };
/// assert_eq!(&*string, "\0\0\0\0\0\0");
/// ```
impl<const CAP: usize> zeroize::Zeroize for ArrayString<CAP> {
fn zeroize(&mut self) {
// There are no elements to drop
self.clear();
// Zeroize the backing array.
self.xs.zeroize();
}
}
26 changes: 26 additions & 0 deletions src/arrayvec.rs
Expand Up @@ -848,6 +848,32 @@ impl<T, const CAP: usize> IntoIterator for ArrayVec<T, CAP> {
}


#[cfg(feature = "zeroize")]
/// "Best efforts" zeroing of the `ArrayVec`'s buffer when the `zeroize` feature is enabled.
///
/// The length is set to 0, and the buffer is dropped and zeroized.
/// Cannot ensure that previous moves of the `ArrayVec` did not leave values on the stack.
///
/// ```
/// use arrayvec::ArrayVec;
/// use zeroize::Zeroize;
/// let mut array = ArrayVec::from([1, 2, 3]);
/// array.zeroize();
/// assert_eq!(array.len(), 0);
/// let data = unsafe { core::slice::from_raw_parts(array.as_ptr(), array.capacity()) };
/// assert_eq!(data, [0, 0, 0]);
/// ```
impl<Z: zeroize::Zeroize, const CAP: usize> zeroize::Zeroize for ArrayVec<Z, CAP> {
fn zeroize(&mut self) {
// Zeroize all the contained elements.
self.iter_mut().zeroize();
// Drop all the elements and set the length to 0.
self.clear();
// Zeroize the backing array.
self.xs.zeroize();
}
}

/// By-value iterator for `ArrayVec`.
pub struct IntoIter<T, const CAP: usize> {
index: usize,
Expand Down

0 comments on commit 2cd12ef

Please sign in to comment.