diff --git a/zeroize/src/lib.rs b/zeroize/src/lib.rs index e2662c2e..0a452163 100644 --- a/zeroize/src/lib.rs +++ b/zeroize/src/lib.rs @@ -626,7 +626,7 @@ impl Zeroize for CString { /// guaranteed to have the same physical representation as the underlying type. #[derive(Debug, Default, Eq, PartialEq)] #[repr(transparent)] -pub struct Zeroizing(Z); +pub struct Zeroizing(Z); impl Zeroizing where @@ -665,7 +665,7 @@ where impl ops::Deref for Zeroizing where - Z: Zeroize, + Z: Zeroize + ?Sized, { type Target = Z; @@ -677,7 +677,7 @@ where impl ops::DerefMut for Zeroizing where - Z: Zeroize, + Z: Zeroize + ?Sized, { #[inline(always)] fn deref_mut(&mut self) -> &mut Z { @@ -688,7 +688,7 @@ where impl AsRef for Zeroizing where T: ?Sized, - Z: AsRef + Zeroize, + Z: AsRef + Zeroize + ?Sized, { #[inline(always)] fn as_ref(&self) -> &T { @@ -699,7 +699,7 @@ where impl AsMut for Zeroizing where T: ?Sized, - Z: AsMut + Zeroize, + Z: AsMut + Zeroize + ?Sized, { #[inline(always)] fn as_mut(&mut self) -> &mut T { @@ -709,18 +709,18 @@ where impl Zeroize for Zeroizing where - Z: Zeroize, + Z: Zeroize + ?Sized, { fn zeroize(&mut self) { self.0.zeroize(); } } -impl ZeroizeOnDrop for Zeroizing where Z: Zeroize {} +impl ZeroizeOnDrop for Zeroizing where Z: Zeroize + ?Sized {} impl Drop for Zeroizing where - Z: Zeroize, + Z: Zeroize + ?Sized, { fn drop(&mut self) { self.0.zeroize() @@ -730,7 +730,7 @@ where #[cfg(feature = "serde")] impl serde::Serialize for Zeroizing where - Z: Zeroize + serde::Serialize, + Z: Zeroize + serde::Serialize + ?Sized, { #[inline(always)] fn serialize(&self, serializer: S) -> Result diff --git a/zeroize/tests/zeroize.rs b/zeroize/tests/zeroize.rs index afc824e0..f462a96f 100644 --- a/zeroize/tests/zeroize.rs +++ b/zeroize/tests/zeroize.rs @@ -4,6 +4,7 @@ use std::{ marker::{PhantomData, PhantomPinned}, mem::{MaybeUninit, size_of}, num::*, + sync::Arc, }; use zeroize::*; @@ -208,3 +209,91 @@ fn asref() { let _asmut: &mut [u8] = buffer.as_mut(); let _asref: &[u8] = buffer.as_ref(); } + +#[cfg(feature = "alloc")] +#[test] +fn box_unsized_zeroizing() { + let mut b: Box> = Box::new(Zeroizing::new([1, 2, 3, 4])); + { + let s: &[u8] = &b; + assert_eq!(s, &[1, 2, 3, 4]); + + let s: &[u8] = b.as_ref(); + assert_eq!(s, &[1, 2, 3, 4]); + + let s: &mut [u8] = b.as_mut(); + assert_eq!(s, &[1, 2, 3, 4]); + } + + unsafe { + core::ptr::drop_in_place(&mut *b); + } + + let s: &[u8] = &b; + assert_eq!(s, &[0, 0, 0, 0]); +} + +#[cfg(feature = "alloc")] +#[test] +fn arc_unsized_zeroizing() { + let mut arc: Arc> = Arc::new(Zeroizing::new([1, 2, 3, 4])); + { + let s: &[u8] = &arc; + assert_eq!(s, &[1, 2, 3, 4]); + + let s: &[u8] = arc.as_ref(); + assert_eq!(s, &[1, 2, 3, 4]); + } + + unsafe { + let inner = Arc::get_mut(&mut arc).unwrap(); + core::ptr::drop_in_place(inner); + } + + let s: &[u8] = &arc; + assert_eq!(s, &[0, 0, 0, 0]); +} + +// This is a weird way to use zeroizing, but it's technically allowed b/c +// unsized types can be stored inside Zeroizing, so make sure it works as +// expected. +#[test] +fn zeroizing_dyn_trait() { + trait TestTrait: Zeroize { + fn data(&self) -> &[u8]; + } + + struct TestStruct { + data: [u8; 4], + } + + impl Zeroize for TestStruct { + fn zeroize(&mut self) { + self.data.zeroize(); + } + } + + impl Drop for TestStruct { + fn drop(&mut self) { + self.zeroize(); + } + } + + impl TestTrait for TestStruct { + fn data(&self) -> &[u8] { + &self.data + } + } + + let mut b: Box> = + Box::new(Zeroizing::new(TestStruct { data: [1, 2, 3, 4] })); + + unsafe { + core::ptr::drop_in_place(&mut *b); + } + + let inner: &Zeroizing = &b; + let inner: &dyn TestTrait = std::ops::Deref::deref(inner); + + assert_eq!(inner.data(), &[0, 0, 0, 0]); +}