Skip to content

Commit 2cd12ef

Browse files
authored
Merge pull request #240 from elichai/zeroize
Optionally implement Zeroize on ArrayVec/ArrayString
2 parents 4ab6d63 + 71200c0 commit 2cd12ef

File tree

4 files changed

+58
-2
lines changed

4 files changed

+58
-2
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,13 @@ jobs:
2222
experimental: false
2323
- rust: stable
2424
features:
25+
bench: true
2526
experimental: false
2627
- rust: beta
2728
features: serde
2829
experimental: false
2930
- rust: nightly
30-
features: serde
31+
features: serde, zeroize
3132
experimental: false
3233

3334
steps:
@@ -57,4 +58,4 @@ jobs:
5758
rustup override set nightly
5859
cargo miri setup
5960
- name: Test with Miri
60-
run: cargo miri test
61+
run: cargo miri test --all-features

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ version = "1.0"
1919
optional = true
2020
default-features = false
2121

22+
[dependencies.zeroize]
23+
version = "1.4"
24+
optional = true
25+
default-features = false
26+
2227
[dev-dependencies.serde_test]
2328
version = "1.0"
2429

src/array_string.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,3 +647,27 @@ impl<'a, const CAP: usize> TryFrom<fmt::Arguments<'a>> for ArrayString<CAP>
647647
Ok(v)
648648
}
649649
}
650+
651+
#[cfg(feature = "zeroize")]
652+
/// "Best efforts" zeroing of the `ArrayString`'s buffer when the `zeroize` feature is enabled.
653+
///
654+
/// The length is set to 0, and the buffer is dropped and zeroized.
655+
/// Cannot ensure that previous moves of the `ArrayString` did not leave values on the stack.
656+
///
657+
/// ```
658+
/// use arrayvec::ArrayString;
659+
/// use zeroize::Zeroize;
660+
/// let mut string = ArrayString::<6>::from("foobar").unwrap();
661+
/// string.zeroize();
662+
/// assert_eq!(string.len(), 0);
663+
/// unsafe { string.set_len(string.capacity()) };
664+
/// assert_eq!(&*string, "\0\0\0\0\0\0");
665+
/// ```
666+
impl<const CAP: usize> zeroize::Zeroize for ArrayString<CAP> {
667+
fn zeroize(&mut self) {
668+
// There are no elements to drop
669+
self.clear();
670+
// Zeroize the backing array.
671+
self.xs.zeroize();
672+
}
673+
}

src/arrayvec.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -848,6 +848,32 @@ impl<T, const CAP: usize> IntoIterator for ArrayVec<T, CAP> {
848848
}
849849

850850

851+
#[cfg(feature = "zeroize")]
852+
/// "Best efforts" zeroing of the `ArrayVec`'s buffer when the `zeroize` feature is enabled.
853+
///
854+
/// The length is set to 0, and the buffer is dropped and zeroized.
855+
/// Cannot ensure that previous moves of the `ArrayVec` did not leave values on the stack.
856+
///
857+
/// ```
858+
/// use arrayvec::ArrayVec;
859+
/// use zeroize::Zeroize;
860+
/// let mut array = ArrayVec::from([1, 2, 3]);
861+
/// array.zeroize();
862+
/// assert_eq!(array.len(), 0);
863+
/// let data = unsafe { core::slice::from_raw_parts(array.as_ptr(), array.capacity()) };
864+
/// assert_eq!(data, [0, 0, 0]);
865+
/// ```
866+
impl<Z: zeroize::Zeroize, const CAP: usize> zeroize::Zeroize for ArrayVec<Z, CAP> {
867+
fn zeroize(&mut self) {
868+
// Zeroize all the contained elements.
869+
self.iter_mut().zeroize();
870+
// Drop all the elements and set the length to 0.
871+
self.clear();
872+
// Zeroize the backing array.
873+
self.xs.zeroize();
874+
}
875+
}
876+
851877
/// By-value iterator for `ArrayVec`.
852878
pub struct IntoIter<T, const CAP: usize> {
853879
index: usize,

0 commit comments

Comments
 (0)