Skip to content

Support Unsized Types in Zeroizing #1256

@ssanderson

Description

@ssanderson

The Zeroizing struct is currently declared with a generic bound of <Z: Zeroize>, which means that Z is implicitly required to be Sized. This means that it's not currently possible to define types like Box<Zeroizing<[T]>> or Arc<Zeroizing<[T]>>, which would be useful in many contexts. In particular, both of these constructions are safer than using Zeroizing<Vec<T>> because they don't support potentially re-allocating resize operations, which can circumvent the desired guarantees of Zeroizing.

It's possible to emulate the functionality of Box<Zeroizing<[T]>> by defining struct like:

struct ZeroizingBox<T: Zeroize + ?Sized>(Box<T>);

impl<T: Zeroize + ?Sized> ZeroizingBox<T> {
    pub fn new(b: Box<T>) -> Self {
        Self(b)
    }
}

impl<T: Zeroize + ?Sized> Drop for ZeroizingBox<T> {
    fn drop(&mut self) {
        self.0.zeroize();
    }
}

but this is a bit cumbersome. I don't think there's a good way to emulate Arc<Zeroizing<[T]>> because there's no way from outside the Arc to mutably access the slice contents in a drop impl. The best you could do is probably Arc<ZeroizingBox<[T]>> using the construction above.

The fix for this would be to update the definition of Zeroizing to:

pub struct Zeroizing<Z: Zeroize + ?Sized>(Z);

Initially I thought that this would be a breaking change, because someone might have written code like:

fn use_by_value<T>(z: Zeroizing<T>) { 
    // ...
}

However, in a case like this the T is implicitly Sized, so there's actually no breakage here. More generally, any code that exists today and forms a Zeroizing<T> must already have an implied or explicit T: Sized bound, so any such code that works today should continue to work without that bound.

It's possible there could be more complex scenarios with breakage breakage involving overlapping blanket trait implementations, but I haven't been able to think of a straightforward one.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions