diff options
Diffstat (limited to 'vendor/zeroize/tests')
-rw-r--r-- | vendor/zeroize/tests/zeroize.rs | 210 | ||||
-rw-r--r-- | vendor/zeroize/tests/zeroize_derive.rs | 317 |
2 files changed, 527 insertions, 0 deletions
diff --git a/vendor/zeroize/tests/zeroize.rs b/vendor/zeroize/tests/zeroize.rs new file mode 100644 index 000000000..32281c1c1 --- /dev/null +++ b/vendor/zeroize/tests/zeroize.rs @@ -0,0 +1,210 @@ +//! zeroize integration tests. + +use std::{ + marker::{PhantomData, PhantomPinned}, + mem::{size_of, MaybeUninit}, + num::*, +}; +use zeroize::*; + +#[cfg(feature = "std")] +use std::ffi::CString; + +#[derive(Clone, Debug, PartialEq)] +struct ZeroizedOnDrop(u64); + +impl Drop for ZeroizedOnDrop { + fn drop(&mut self) { + self.0.zeroize(); + } +} + +#[test] +fn non_zero() { + macro_rules! non_zero_test { + ($($type:ty),+) => { + $(let mut value = <$type>::new(42).unwrap(); + value.zeroize(); + assert_eq!(value.get(), 1);)+ + }; + } + + non_zero_test!( + NonZeroI8, + NonZeroI16, + NonZeroI32, + NonZeroI64, + NonZeroI128, + NonZeroIsize, + NonZeroU8, + NonZeroU16, + NonZeroU32, + NonZeroU64, + NonZeroU128, + NonZeroUsize + ); +} + +#[test] +fn zeroize_byte_arrays() { + let mut arr = [42u8; 137]; + arr.zeroize(); + assert_eq!(arr.as_ref(), [0u8; 137].as_ref()); +} + +#[test] +fn zeroize_on_drop_byte_arrays() { + let mut arr = [ZeroizedOnDrop(42); 1]; + unsafe { core::ptr::drop_in_place(&mut arr) }; + assert_eq!(arr.as_ref(), [ZeroizedOnDrop(0); 1].as_ref()); +} + +#[test] +fn zeroize_maybeuninit_byte_arrays() { + let mut arr = [MaybeUninit::new(42u64); 64]; + arr.zeroize(); + let arr_init: [u64; 64] = unsafe { core::mem::transmute(arr) }; + assert_eq!(arr_init, [0u64; 64]); +} + +#[test] +fn zeroize_check_zerosize_types() { + // Since we assume these types have zero size, we test this holds for + // the current version of Rust. + assert_eq!(size_of::<()>(), 0); + assert_eq!(size_of::<PhantomPinned>(), 0); + assert_eq!(size_of::<PhantomData<usize>>(), 0); +} + +#[test] +fn zeroize_check_tuple() { + let mut tup1 = (42u8,); + tup1.zeroize(); + assert_eq!(tup1, (0u8,)); + + let mut tup2 = (42u8, 42u8); + tup2.zeroize(); + assert_eq!(tup2, (0u8, 0u8)); +} + +#[test] +fn zeroize_on_drop_check_tuple() { + let mut tup1 = (ZeroizedOnDrop(42),); + unsafe { core::ptr::drop_in_place(&mut tup1) }; + assert_eq!(tup1, (ZeroizedOnDrop(0),)); + + let mut tup2 = (ZeroizedOnDrop(42), ZeroizedOnDrop(42)); + unsafe { core::ptr::drop_in_place(&mut tup2) }; + assert_eq!(tup2, (ZeroizedOnDrop(0), ZeroizedOnDrop(0))); +} + +#[cfg(feature = "alloc")] +#[test] +fn zeroize_vec() { + let mut vec = vec![42; 3]; + vec.zeroize(); + assert!(vec.is_empty()); +} + +#[cfg(feature = "alloc")] +#[test] +fn zeroize_vec_entire_capacity() { + #[derive(Clone)] + struct PanicOnNonZeroDrop(u64); + + impl Zeroize for PanicOnNonZeroDrop { + fn zeroize(&mut self) { + self.0 = 0; + } + } + + impl Drop for PanicOnNonZeroDrop { + fn drop(&mut self) { + if self.0 != 0 { + panic!("dropped non-zeroized data"); + } + } + } + + // Ensure that the entire capacity of the vec is zeroized and that no unitinialized data + // is ever interpreted as initialized + let mut vec = vec![PanicOnNonZeroDrop(42); 2]; + + unsafe { + vec.set_len(1); + } + + vec.zeroize(); + + unsafe { + vec.set_len(2); + } + + drop(vec); +} + +#[cfg(feature = "alloc")] +#[test] +fn zeroize_string() { + let mut string = String::from("Hello, world!"); + string.zeroize(); + assert!(string.is_empty()); +} + +#[cfg(feature = "alloc")] +#[test] +fn zeroize_string_entire_capacity() { + let mut string = String::from("Hello, world!"); + string.truncate(5); + + string.zeroize(); + + // convert the string to a vec to easily access the unused capacity + let mut as_vec = string.into_bytes(); + unsafe { as_vec.set_len(as_vec.capacity()) }; + + assert!(as_vec.iter().all(|byte| *byte == 0)); +} + +// TODO(tarcieri): debug flaky test (with potential UB?) See: RustCrypto/utils#774 +#[cfg(feature = "std")] +#[ignore] +#[test] +fn zeroize_c_string() { + let mut cstring = CString::new("Hello, world!").expect("CString::new failed"); + let orig_len = cstring.as_bytes().len(); + let orig_ptr = cstring.as_bytes().as_ptr(); + cstring.zeroize(); + // This doesn't quite test that the original memory has been cleared, but only that + // cstring now owns an empty buffer + assert!(cstring.as_bytes().is_empty()); + for i in 0..orig_len { + unsafe { + // Using a simple deref, only one iteration of the loop is performed + // presumably because after zeroize, the internal buffer has a length of one/ + // `read_volatile` seems to "fix" this + // Note that this is very likely UB + assert_eq!(orig_ptr.add(i).read_volatile(), 0); + } + } +} + +#[cfg(feature = "alloc")] +#[test] +fn zeroize_box() { + let mut boxed_arr = Box::new([42u8; 3]); + boxed_arr.zeroize(); + assert_eq!(boxed_arr.as_ref(), &[0u8; 3]); +} + +#[cfg(feature = "alloc")] +#[test] +fn asref() { + let mut buffer: Zeroizing<Vec<u8>> = Default::default(); + let _asmut: &mut [u8] = buffer.as_mut(); + let _asref: &[u8] = buffer.as_ref(); + + let mut buffer: Zeroizing<Box<[u8]>> = Default::default(); + let _asmut: &mut [u8] = buffer.as_mut(); + let _asref: &[u8] = buffer.as_ref(); +} diff --git a/vendor/zeroize/tests/zeroize_derive.rs b/vendor/zeroize/tests/zeroize_derive.rs new file mode 100644 index 000000000..4e0fdc61c --- /dev/null +++ b/vendor/zeroize/tests/zeroize_derive.rs @@ -0,0 +1,317 @@ +//! Integration tests for `zeroize_derive` proc macros +#![cfg(feature = "zeroize_derive")] + +use zeroize::{Zeroize, ZeroizeOnDrop}; + +#[test] +fn derive_tuple_struct_test() { + #[derive(Zeroize, ZeroizeOnDrop)] + struct Z([u8; 3]); + + let mut value = Z([1, 2, 3]); + value.zeroize(); + assert_eq!(&value.0, &[0, 0, 0]) +} + +#[test] +#[cfg(feature = "alloc")] +fn derive_struct_test() { + #[derive(Zeroize, ZeroizeOnDrop)] + struct Z { + string: String, + vec: Vec<u8>, + bytearray: [u8; 3], + number: usize, + boolean: bool, + } + + let mut value = Z { + string: String::from("Hello, world!"), + vec: vec![1, 2, 3], + bytearray: [4, 5, 6], + number: 42, + boolean: true, + }; + + value.zeroize(); + + assert!(value.string.is_empty()); + assert!(value.vec.is_empty()); + assert_eq!(&value.bytearray, &[0, 0, 0]); + assert_eq!(value.number, 0); + assert!(!value.boolean); +} + +#[test] +fn derive_enum_test() { + #[derive(Zeroize, ZeroizeOnDrop)] + enum Z { + #[allow(dead_code)] + Variant1, + Variant2(usize), + } + + let mut value = Z::Variant2(26); + + value.zeroize(); + + assert!(matches!(value, Z::Variant2(0))); +} + +/// Test that the custom macro actually derived `Drop` for `Z` +#[test] +fn derive_struct_drop() { + #[derive(Zeroize, ZeroizeOnDrop)] + struct Z([u8; 3]); + + assert!(std::mem::needs_drop::<Z>()); +} + +/// Test that the custom macro actually derived `Drop` for `Z` +#[test] +fn derive_enum_drop() { + #[allow(dead_code)] + #[derive(Zeroize, ZeroizeOnDrop)] + enum Z { + Variant1, + Variant2(usize), + } + + assert!(std::mem::needs_drop::<Z>()); +} + +/// Test that the custom macro actually derived `Drop` for `Z` +#[test] +fn derive_struct_only_drop() { + #[derive(ZeroizeOnDrop)] + struct Z([u8; 3]); + + assert!(std::mem::needs_drop::<Z>()); +} + +/// Test that the custom macro actually derived `Drop` for `Z` +#[test] +fn derive_enum_only_drop() { + #[allow(dead_code)] + #[derive(ZeroizeOnDrop)] + enum Z { + Variant1, + Variant2(usize), + } + + assert!(std::mem::needs_drop::<Z>()); +} + +/// Test that `Drop` is not derived in the following case by defining a +/// `Drop` impl which should conflict if the custom derive defined one too +#[allow(dead_code)] +#[derive(Zeroize)] +struct ZeroizeNoDropStruct([u8; 3]); + +impl Drop for ZeroizeNoDropStruct { + fn drop(&mut self) {} +} + +#[allow(dead_code)] +#[derive(Zeroize)] +enum ZeroizeNoDropEnum { + Variant([u8; 3]), +} + +impl Drop for ZeroizeNoDropEnum { + fn drop(&mut self) {} +} + +#[test] +#[cfg(feature = "alloc")] +fn derive_struct_skip() { + #[derive(Zeroize, ZeroizeOnDrop)] + struct Z { + string: String, + vec: Vec<u8>, + #[zeroize(skip)] + bytearray: [u8; 3], + number: usize, + boolean: bool, + } + + let mut value = Z { + string: String::from("Hello, world!"), + vec: vec![1, 2, 3], + bytearray: [4, 5, 6], + number: 42, + boolean: true, + }; + + value.zeroize(); + + assert!(value.string.is_empty()); + assert!(value.vec.is_empty()); + assert_eq!(&value.bytearray, &[4, 5, 6]); + assert_eq!(value.number, 0); + assert!(!value.boolean); +} + +#[test] +#[cfg(feature = "alloc")] +fn derive_enum_skip() { + #[derive(Zeroize, ZeroizeOnDrop)] + enum Z { + #[allow(dead_code)] + Variant1, + #[zeroize(skip)] + Variant2([u8; 3]), + #[zeroize(skip)] + Variant3 { + string: String, + vec: Vec<u8>, + bytearray: [u8; 3], + number: usize, + boolean: bool, + }, + Variant4 { + string: String, + vec: Vec<u8>, + #[zeroize(skip)] + bytearray: [u8; 3], + number: usize, + boolean: bool, + }, + } + + let mut value = Z::Variant2([4, 5, 6]); + + value.zeroize(); + + assert!(matches!(&value, Z::Variant2([4, 5, 6]))); + + let mut value = Z::Variant3 { + string: String::from("Hello, world!"), + vec: vec![1, 2, 3], + bytearray: [4, 5, 6], + number: 42, + boolean: true, + }; + + value.zeroize(); + + assert!(matches!( + &value, + Z::Variant3 { string, vec, bytearray, number, boolean } + if string == "Hello, world!" && + vec == &[1, 2, 3] && + bytearray == &[4, 5, 6] && + *number == 42 && + *boolean + )); + + let mut value = Z::Variant4 { + string: String::from("Hello, world!"), + vec: vec![1, 2, 3], + bytearray: [4, 5, 6], + number: 42, + boolean: true, + }; + + value.zeroize(); + + assert!(matches!( + &value, + Z::Variant4 { string, vec, bytearray, number, boolean } + if string.is_empty() && + vec.is_empty() && + bytearray == &[4, 5, 6] && + *number == 0 && + !boolean + )); +} + +#[test] +fn derive_bound() { + trait T: Zeroize {} + + impl T for u8 {} + + #[derive(Zeroize)] + #[zeroize(bound = "X: T")] + struct Z<X>(X); + + let mut value = Z(5_u8); + + value.zeroize(); + + assert_eq!(value.0, 0); +} + +#[test] +fn derive_inherit_zeroize_on_drop() { + #[derive(ZeroizeOnDrop)] + struct X([u8; 3]); + + #[derive(ZeroizeOnDrop)] + struct Z(X); + + let mut value = Z(X([1, 2, 3])); + unsafe { + std::ptr::drop_in_place(&mut value); + } + assert_eq!(&value.0 .0, &[0, 0, 0]) +} + +#[test] +fn derive_inherit_from_both() { + #[derive(Zeroize, ZeroizeOnDrop)] + struct X([u8; 3]); + + #[derive(ZeroizeOnDrop)] + struct Z(X); + + let mut value = Z(X([1, 2, 3])); + unsafe { + std::ptr::drop_in_place(&mut value); + } + assert_eq!(&value.0 .0, &[0, 0, 0]) +} + +#[test] +fn derive_inherit_both() { + #[derive(Zeroize, ZeroizeOnDrop)] + struct X([u8; 3]); + + #[derive(Zeroize, ZeroizeOnDrop)] + struct Z(X); + + let mut value = Z(X([1, 2, 3])); + unsafe { + std::ptr::drop_in_place(&mut value); + } + assert_eq!(&value.0 .0, &[0, 0, 0]) +} + +#[test] +fn derive_deref() { + struct X([u8; 3]); + + impl std::ops::Deref for X { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + impl std::ops::DerefMut for X { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } + } + + #[derive(Zeroize, ZeroizeOnDrop)] + struct Z(X); + + let mut value = Z(X([1, 2, 3])); + unsafe { + std::ptr::drop_in_place(&mut value); + } + assert_eq!(&value.0 .0, &[0, 0, 0]) +} |