Skip to content

Commit c20be21

Browse files
committed
zeroize: support unsized types in Zeroizing
This commit adds ?Sized to the generic bounds on Zeroizing and many of its trait implementations. This makes it possible to form and use types like `Zeroizing<Box<[u8]>>` and `Zeroizing<Arc<[u8]>>`.
1 parent 300c312 commit c20be21

File tree

2 files changed

+99
-10
lines changed

2 files changed

+99
-10
lines changed

zeroize/src/lib.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ impl Zeroize for CString {
626626
/// guaranteed to have the same physical representation as the underlying type.
627627
#[derive(Debug, Default, Eq, PartialEq)]
628628
#[repr(transparent)]
629-
pub struct Zeroizing<Z: Zeroize>(Z);
629+
pub struct Zeroizing<Z: Zeroize + ?Sized>(Z);
630630

631631
impl<Z> Zeroizing<Z>
632632
where
@@ -665,7 +665,7 @@ where
665665

666666
impl<Z> ops::Deref for Zeroizing<Z>
667667
where
668-
Z: Zeroize,
668+
Z: Zeroize + ?Sized,
669669
{
670670
type Target = Z;
671671

@@ -677,7 +677,7 @@ where
677677

678678
impl<Z> ops::DerefMut for Zeroizing<Z>
679679
where
680-
Z: Zeroize,
680+
Z: Zeroize + ?Sized,
681681
{
682682
#[inline(always)]
683683
fn deref_mut(&mut self) -> &mut Z {
@@ -688,7 +688,7 @@ where
688688
impl<T, Z> AsRef<T> for Zeroizing<Z>
689689
where
690690
T: ?Sized,
691-
Z: AsRef<T> + Zeroize,
691+
Z: AsRef<T> + Zeroize + ?Sized,
692692
{
693693
#[inline(always)]
694694
fn as_ref(&self) -> &T {
@@ -699,7 +699,7 @@ where
699699
impl<T, Z> AsMut<T> for Zeroizing<Z>
700700
where
701701
T: ?Sized,
702-
Z: AsMut<T> + Zeroize,
702+
Z: AsMut<T> + Zeroize + ?Sized,
703703
{
704704
#[inline(always)]
705705
fn as_mut(&mut self) -> &mut T {
@@ -709,18 +709,18 @@ where
709709

710710
impl<Z> Zeroize for Zeroizing<Z>
711711
where
712-
Z: Zeroize,
712+
Z: Zeroize + ?Sized,
713713
{
714714
fn zeroize(&mut self) {
715715
self.0.zeroize();
716716
}
717717
}
718718

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

721721
impl<Z> Drop for Zeroizing<Z>
722722
where
723-
Z: Zeroize,
723+
Z: Zeroize + ?Sized,
724724
{
725725
fn drop(&mut self) {
726726
self.0.zeroize()
@@ -730,7 +730,7 @@ where
730730
#[cfg(feature = "serde")]
731731
impl<Z> serde::Serialize for Zeroizing<Z>
732732
where
733-
Z: Zeroize + serde::Serialize,
733+
Z: Zeroize + serde::Serialize + ?Sized,
734734
{
735735
#[inline(always)]
736736
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -744,7 +744,7 @@ where
744744
#[cfg(feature = "serde")]
745745
impl<'de, Z> serde::Deserialize<'de> for Zeroizing<Z>
746746
where
747-
Z: Zeroize + serde::Deserialize<'de>,
747+
Z: Zeroize + serde::Deserialize<'de>
748748
{
749749
#[inline(always)]
750750
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>

zeroize/tests/zeroize.rs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::{
44
marker::{PhantomData, PhantomPinned},
55
mem::{MaybeUninit, size_of},
66
num::*,
7+
sync::Arc,
78
};
89
use zeroize::*;
910

@@ -208,3 +209,91 @@ fn asref() {
208209
let _asmut: &mut [u8] = buffer.as_mut();
209210
let _asref: &[u8] = buffer.as_ref();
210211
}
212+
213+
#[cfg(feature = "alloc")]
214+
#[test]
215+
fn box_unsized_zeroizing() {
216+
let mut b: Box<Zeroizing<[u8]>> = Box::new(Zeroizing::new([1, 2, 3, 4]));
217+
{
218+
let s: &[u8] = &b;
219+
assert_eq!(s, &[1, 2, 3, 4]);
220+
221+
let s: &[u8] = b.as_ref();
222+
assert_eq!(s, &[1, 2, 3, 4]);
223+
224+
let s: &mut [u8] = b.as_mut();
225+
assert_eq!(s, &[1, 2, 3, 4]);
226+
}
227+
228+
unsafe {
229+
core::ptr::drop_in_place(&mut *b);
230+
}
231+
232+
let s: &[u8] = &b;
233+
assert_eq!(s, &[0, 0, 0, 0]);
234+
}
235+
236+
#[cfg(feature = "alloc")]
237+
#[test]
238+
fn arc_unsized_zeroizing() {
239+
let mut arc: Arc<Zeroizing<[u8]>> = Arc::new(Zeroizing::new([1, 2, 3, 4]));
240+
{
241+
let s: &[u8] = &arc;
242+
assert_eq!(s, &[1, 2, 3, 4]);
243+
244+
let s: &[u8] = arc.as_ref();
245+
assert_eq!(s, &[1, 2, 3, 4]);
246+
}
247+
248+
unsafe {
249+
let inner = Arc::get_mut(&mut arc).unwrap();
250+
core::ptr::drop_in_place(inner);
251+
}
252+
253+
let s: &[u8] = &arc;
254+
assert_eq!(s, &[0, 0, 0, 0]);
255+
}
256+
257+
// This is a weird way to use zeroizing, but it's technically allowed b/c
258+
// unsized types can be stored inside Zeroizing, so make sure it works as
259+
// expected.
260+
#[test]
261+
fn zeroizing_dyn_trait() {
262+
trait TestTrait: Zeroize {
263+
fn data(&self) -> &[u8];
264+
}
265+
266+
struct TestStruct {
267+
data: [u8; 4],
268+
}
269+
270+
impl Zeroize for TestStruct {
271+
fn zeroize(&mut self) {
272+
self.data.zeroize();
273+
}
274+
}
275+
276+
impl Drop for TestStruct {
277+
fn drop(&mut self) {
278+
self.zeroize();
279+
}
280+
}
281+
282+
impl TestTrait for TestStruct {
283+
fn data(&self) -> &[u8] {
284+
&self.data
285+
}
286+
}
287+
288+
let mut b: Box<Zeroizing<dyn TestTrait>> =
289+
Box::new(Zeroizing::new(TestStruct { data: [1, 2, 3, 4] }));
290+
291+
unsafe {
292+
core::ptr::drop_in_place(&mut *b);
293+
}
294+
295+
let inner: &Zeroizing<dyn TestTrait> = &b;
296+
let inner: &dyn TestTrait = std::ops::Deref::deref(inner);
297+
298+
assert_eq!(inner.data(), &[0, 0, 0, 0]);
299+
}

0 commit comments

Comments
 (0)