Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions zeroize/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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: Zeroize>(Z);
pub struct Zeroizing<Z: Zeroize + ?Sized>(Z);

impl<Z> Zeroizing<Z>
where
Expand Down Expand Up @@ -665,7 +665,7 @@ where

impl<Z> ops::Deref for Zeroizing<Z>
where
Z: Zeroize,
Z: Zeroize + ?Sized,
{
type Target = Z;

Expand All @@ -677,7 +677,7 @@ where

impl<Z> ops::DerefMut for Zeroizing<Z>
where
Z: Zeroize,
Z: Zeroize + ?Sized,
{
#[inline(always)]
fn deref_mut(&mut self) -> &mut Z {
Expand All @@ -688,7 +688,7 @@ where
impl<T, Z> AsRef<T> for Zeroizing<Z>
where
T: ?Sized,
Z: AsRef<T> + Zeroize,
Z: AsRef<T> + Zeroize + ?Sized,
{
#[inline(always)]
fn as_ref(&self) -> &T {
Expand All @@ -699,7 +699,7 @@ where
impl<T, Z> AsMut<T> for Zeroizing<Z>
where
T: ?Sized,
Z: AsMut<T> + Zeroize,
Z: AsMut<T> + Zeroize + ?Sized,
{
#[inline(always)]
fn as_mut(&mut self) -> &mut T {
Expand All @@ -709,18 +709,18 @@ where

impl<Z> Zeroize for Zeroizing<Z>
where
Z: Zeroize,
Z: Zeroize + ?Sized,
{
fn zeroize(&mut self) {
self.0.zeroize();
}
}

impl<Z> ZeroizeOnDrop for Zeroizing<Z> where Z: Zeroize {}
impl<Z> ZeroizeOnDrop for Zeroizing<Z> where Z: Zeroize + ?Sized {}

impl<Z> Drop for Zeroizing<Z>
where
Z: Zeroize,
Z: Zeroize + ?Sized,
{
fn drop(&mut self) {
self.0.zeroize()
Expand All @@ -730,7 +730,7 @@ where
#[cfg(feature = "serde")]
impl<Z> serde::Serialize for Zeroizing<Z>
where
Z: Zeroize + serde::Serialize,
Z: Zeroize + serde::Serialize + ?Sized,
{
#[inline(always)]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
Expand Down
89 changes: 89 additions & 0 deletions zeroize/tests/zeroize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::{
marker::{PhantomData, PhantomPinned},
mem::{MaybeUninit, size_of},
num::*,
sync::Arc,
};
use zeroize::*;

Expand Down Expand Up @@ -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<Zeroizing<[u8]>> = 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<Zeroizing<[u8]>> = 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]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is missing a feature = "alloc" guard since it uses Box, but it seems like the build is still passing. Are these guards actually required?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since these tests are in tests/ they're in their own toplevel crate which links alloc and std by default.

You only need to gate alloc if it's using alloc-dependent functionality inside Zeroize. Since this is Box<Zeroizing<[u8]>> and not Zeroizing<Box<[u8]>> (which would need the Zeroize impl on Box) you're not actually dependent on zeroize having its alloc feature enabled.

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<Zeroizing<dyn TestTrait>> =
Box::new(Zeroizing::new(TestStruct { data: [1, 2, 3, 4] }));

unsafe {
core::ptr::drop_in_place(&mut *b);
}

let inner: &Zeroizing<dyn TestTrait> = &b;
let inner: &dyn TestTrait = std::ops::Deref::deref(inner);

assert_eq!(inner.data(), &[0, 0, 0, 0]);
}