Skip to content

Commit

Permalink
Implement ZeroizeOnDrop
Browse files Browse the repository at this point in the history
  • Loading branch information
daxpedda committed Jan 5, 2022
1 parent bcd69ae commit 9d05a78
Show file tree
Hide file tree
Showing 17 changed files with 352 additions and 149 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Added
- Support `ZeroizeOnDrop`.

### Removed
- **Breaking Change**: Remove support for `Zeroize(drop)`.

## [1.0.0-rc.1] - 2021-12-08
### Added
- Initial release.

[Unreleased]: https://github.com/ModProg/derive-where/compare/v1.0.0-rc.1...HEAD
[1.0.0-rc.1]: https://github.com/ModProg/derive-where/releases/tag/v1.0.0-rc.1
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ syn = { version = "1", default-features = false, features = [
[dev-dependencies]
syn = { version = "1", default-features = false, features = ["extra-traits"] }

[patch.crates-io]
zeroize = { git = "https://github.com/khonsulabs/utils", branch = "zeroize-on-drop-auto-deref" }

[[test]]
name = "util"
path = "tests/util.rs"
Expand Down
26 changes: 20 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ enum Example<T> {

With a `skip` or `skip_inner` attribute fields can be skipped for traits
that allow it, which are: [`Debug`], [`Hash`], [`Ord`](https://doc.rust-lang.org/core/cmp/trait.Ord.html), [`PartialOrd`](https://doc.rust-lang.org/core/cmp/trait.PartialOrd.html),
[`PartialEq`](https://doc.rust-lang.org/core/cmp/trait.PartialEq.html) and [`Zeroize`].
[`PartialEq`](https://doc.rust-lang.org/core/cmp/trait.PartialEq.html), [`Zeroize`] and [`ZeroizeOnDrop`].

```rust
#[derive(DeriveWhere)]
Expand Down Expand Up @@ -148,18 +148,16 @@ assert_ne!(

### `Zeroize` options

[`Zeroize`] has three options:
[`Zeroize`] has two options:
- `crate`: an item-level option which specifies a path to the `zeroize`
crate in case of a re-export or rename.
- `drop`: an item-level option which implements [`Drop`](https://doc.rust-lang.org/core/ops/trait.Drop.html) and uses
[`Zeroize`] to erase all data from memory.
- `fqs`: a field -level option which will use fully-qualified-syntax instead
of calling the [`zeroize`][`method@zeroize`] method on `self` directly.
This is to avoid ambiguity between another method also called `zeroize`.

```rust
#[derive(DeriveWhere)]
#[derive_where(Zeroize(crate = "zeroize_", drop))]
#[derive_where(Zeroize(crate = "zeroize_"))]
struct Example(#[derive_where(Zeroize(fqs))] i32);

impl Example {
Expand All @@ -181,6 +179,20 @@ Zeroize::zeroize(&mut test);
assert_eq!(test.0, 0);
```

### `ZeroizeOnDrop` options

[`ZeroizeOnDrop`] has one option:
- `crate`: an item-level option which specifies a path to the `zeroize`
crate in case of a re-export or rename.

```
#[derive(DeriveWhere)]
#[derive_where(ZeroizeOnDrop(crate = "zeroize_"))]
struct Example(i32);
assert!(core::mem::needs_drop::<Example>());
```

### Supported traits

The following traits can be derived with derive-where:
Expand All @@ -194,6 +206,7 @@ The following traits can be derived with derive-where:
- [`PartialEq`](https://doc.rust-lang.org/core/cmp/trait.PartialEq.html)
- [`PartialOrd`](https://doc.rust-lang.org/core/cmp/trait.PartialOrd.html)
- [`Zeroize`]: Only available with the `zeroize` crate feature.
- [`ZeroizeOnDrop`]: Only available with the `zeroize` crate feature.

### Supported items

Expand All @@ -220,7 +233,7 @@ Unions only support [`Clone`](https://doc.rust-lang.org/core/clone/trait.Clone.h
replaces all cases of [`core::hint::unreachable_unchecked`](https://doc.rust-lang.org/core/hint/fn.unreachable_unchecked.html) in [`Ord`](https://doc.rust-lang.org/core/hint/fn.unreachable_unchecked.html),
[`PartialEq`](https://doc.rust-lang.org/core/cmp/trait.PartialEq.html) and [`PartialOrd`](https://doc.rust-lang.org/core/cmp/trait.PartialOrd.html), which is what std uses, with
[`unreachable`](https://doc.rust-lang.org/core/macro.unreachable.html).
- `zeroize`: Allows deriving [`Zeroize`].
- `zeroize`: Allows deriving [`Zeroize`] and [`ZeroizeOnDrop`].

## MSRV

Expand Down Expand Up @@ -262,5 +275,6 @@ conditions.
[`Default`]: https://doc.rust-lang.org/core/default/trait.Default.html
[`Hash`]: https://doc.rust-lang.org/core/hash/trait.Hash.html
[`Zeroize`]: https://docs.rs/zeroize/latest/zeroize/trait.Zeroize.html
[`ZeroizeOnDrop`]: https://docs.rs/zeroize/latest/zeroize/trait.ZeroizeOnDrop.html
[`method@zeroize`]: https://docs.rs/zeroize/latest/zeroize/trait.Zeroize.html#tymethod.zeroize
[#27]: https://github.com/ModProg/derive-where/issues/27
2 changes: 1 addition & 1 deletion ensure-no-std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ use derive_where::DeriveWhere;
#[derive(DeriveWhere)]
#[derive_where(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "zeroize", derive_where(Zeroize))]
pub struct Test<T>(#[cfg_attr(feature = "zeroize", derive_where(skip(Zeroize)))] PhantomData<T>);
pub struct Test<T>(PhantomData<T>);
12 changes: 6 additions & 6 deletions non-msrv-tests/tests/ui/zeroize/item.stderr
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
error: unsupported trait, expected one of expected one of Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Zeroize
error: unsupported trait, expected one of expected one of Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Zeroize, ZeroizeOnDrop
--> tests/ui/zeroize/item.rs:6:16
|
6 | #[derive_where(skip_inner, Clone)]
| ^^^^^^^^^^

error: unsupported trait syntax, expected one of expected one of Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Zeroize
error: unsupported trait syntax, expected one of expected one of Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Zeroize, ZeroizeOnDrop
--> tests/ui/zeroize/item.rs:10:24
|
10 | #[derive_where(Debug = invalid; T)]
| ^^^^^^^

error: unsupported trait syntax, expected one of expected one of Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Zeroize
error: unsupported trait syntax, expected one of expected one of Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Zeroize, ZeroizeOnDrop
--> tests/ui/zeroize/item.rs:14:16
|
14 | #[derive_where(,)]
| ^

error: unsupported trait syntax, expected one of expected one of Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Zeroize
error: unsupported trait syntax, expected one of expected one of Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Zeroize, ZeroizeOnDrop
--> tests/ui/zeroize/item.rs:18:16
|
18 | #[derive_where(,Clone)]
| ^

error: unsupported trait syntax, expected one of expected one of Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Zeroize
error: unsupported trait syntax, expected one of expected one of Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Zeroize, ZeroizeOnDrop
--> tests/ui/zeroize/item.rs:22:22
|
22 | #[derive_where(Clone,,)]
| ^

error: unsupported trait, expected one of expected one of Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Zeroize
error: unsupported trait, expected one of expected one of Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Zeroize, ZeroizeOnDrop
--> tests/ui/zeroize/item.rs:26:16
|
26 | #[derive_where(T)]
Expand Down
20 changes: 0 additions & 20 deletions non-msrv-tests/tests/ui/zeroize/zeroize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,28 +24,8 @@ struct WrongCrateSyntax<T>(PhantomData<T>);
#[derive_where(Zeroize(crate = "struct Test"))]
struct InvalidCrate<T>(PhantomData<T>);

#[derive(DeriveWhere)]
#[derive_where(Zeroize(drop, drop))]
struct DuplicateDrop<T>(PhantomData<T>);

#[derive(DeriveWhere)]
#[derive_where(Zeroize(crate = "zeroize_", crate = "zeroize_"))]
struct DuplicateCrate<T>(PhantomData<T>);

#[derive(DeriveWhere)]
#[derive_where(Zeroize(drop, drop, crate = "zeroize_"))]
struct DuplicateDropWithCrate<T>(PhantomData<T>);

#[derive(DeriveWhere)]
#[derive_where(Zeroize(drop, crate = "zeroize_", crate = "zeroize_"))]
struct DropWithDuplicateCrate<T>(PhantomData<T>);

#[derive(DeriveWhere)]
#[derive_where(Zeroize(crate = "zeroize_", crate = "zeroize_", drop))]
struct DuplicateCrateWithDrop<T>(PhantomData<T>);

#[derive(DeriveWhere)]
#[derive_where(Zeroize(crate = "zeroize_", drop, drop))]
struct CrateWithDuplicateDrop<T>(PhantomData<T>);

fn main() {}
34 changes: 2 additions & 32 deletions non-msrv-tests/tests/ui/zeroize/zeroize.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -28,38 +28,8 @@ error: expected path, expected identifier
24 | #[derive_where(Zeroize(crate = "struct Test"))]
| ^^^^^^^^^^^^^

error: duplicate `drop` option
--> tests/ui/zeroize/zeroize.rs:28:30
|
28 | #[derive_where(Zeroize(drop, drop))]
| ^^^^

error: duplicate `crate` option
--> tests/ui/zeroize/zeroize.rs:32:44
--> tests/ui/zeroize/zeroize.rs:28:44
|
32 | #[derive_where(Zeroize(crate = "zeroize_", crate = "zeroize_"))]
28 | #[derive_where(Zeroize(crate = "zeroize_", crate = "zeroize_"))]
| ^^^^^^^^^^^^^^^^^^

error: duplicate `drop` option
--> tests/ui/zeroize/zeroize.rs:36:30
|
36 | #[derive_where(Zeroize(drop, drop, crate = "zeroize_"))]
| ^^^^

error: duplicate `crate` option
--> tests/ui/zeroize/zeroize.rs:40:50
|
40 | #[derive_where(Zeroize(drop, crate = "zeroize_", crate = "zeroize_"))]
| ^^^^^^^^^^^^^^^^^^

error: duplicate `crate` option
--> tests/ui/zeroize/zeroize.rs:44:44
|
44 | #[derive_where(Zeroize(crate = "zeroize_", crate = "zeroize_", drop))]
| ^^^^^^^^^^^^^^^^^^

error: duplicate `drop` option
--> tests/ui/zeroize/zeroize.rs:48:50
|
48 | #[derive_where(Zeroize(crate = "zeroize_", drop, drop))]
| ^^^^
5 changes: 4 additions & 1 deletion non-msrv-tests/tests/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{
};

#[cfg(feature = "zeroize")]
use zeroize_::Zeroize;
use zeroize_::{Zeroize, ZeroizeOnDrop};

pub struct Wrapper<T = ()> {
data: i32,
Expand Down Expand Up @@ -44,6 +44,9 @@ impl<T> Zeroize for Wrapper<T> {
#[cfg(feature = "zeroize")]
pub struct AssertZeroize<'a, T: Zeroize>(pub &'a T);

#[cfg(feature = "zeroize")]
pub struct AssertZeroizeOnDrop<'a, T: ZeroizeOnDrop>(pub &'a T);

pub fn test_drop<T>(value: T, fun: impl FnOnce(&T)) {
let mut test_holder = vec![value];
let ptr = &mut test_holder[0] as *mut T;
Expand Down
11 changes: 7 additions & 4 deletions non-msrv-tests/tests/zeroize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use std::{
use derive_where::DeriveWhere;
use zeroize::Zeroize;

use self::util::{AssertZeroize, Wrapper};
use self::util::{AssertZeroize, AssertZeroizeOnDrop, Wrapper};

#[test]
fn basic() {
Expand Down Expand Up @@ -51,12 +51,13 @@ fn crate_() {
#[test]
fn drop() {
#[derive(DeriveWhere)]
#[derive_where(Zeroize(drop))]
#[derive_where(Zeroize, ZeroizeOnDrop)]
struct Test<T>(Wrapper<T>);

let mut test = Test(42.into());

let _ = AssertZeroize(&test);
let _ = AssertZeroizeOnDrop(&test);

test.zeroize();

Expand All @@ -83,12 +84,13 @@ fn fqs() {
}

#[derive(DeriveWhere)]
#[derive_where(Zeroize(drop))]
#[derive_where(Zeroize, ZeroizeOnDrop)]
struct Test<T>(#[derive_where(Zeroize(fqs))] Fqs<T>);

let mut test = Test(Fqs(42.into()));

let _ = AssertZeroize(&test);
let _ = AssertZeroizeOnDrop(&test);

test.zeroize();

Expand Down Expand Up @@ -116,12 +118,13 @@ fn deref() {
}

#[derive(DeriveWhere)]
#[derive_where(Zeroize(drop))]
#[derive_where(Zeroize, ZeroizeOnDrop)]
struct Test<T>(ZeroizeDeref<T>);

let mut test = Test::<()>(ZeroizeDeref(42, PhantomData));

let _ = AssertZeroize(&test);
let _ = AssertZeroizeOnDrop(&test);

test.zeroize();

Expand Down
20 changes: 18 additions & 2 deletions src/attr/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,12 @@ pub enum DeriveTrait {
Zeroize {
/// [`Zeroize`](https://docs.rs/zeroize/latest/zeroize/trait.Zeroize.html) path.
crate_: Option<Path>,
/// [`Zeroize`](https://docs.rs/zeroize/latest/zeroize/trait.Zeroize.html) [`Drop`] implementation.
drop: bool,
},
/// [`ZeroizeOnDrop`](https://docs.rs/zeroize/latest/zeroize/trait.ZeroizeOnDrop.html).
#[cfg(feature = "zeroize")]
ZeroizeOnDrop {
/// [`ZeroizeOnDrop`](https://docs.rs/zeroize/latest/zeroize/trait.ZeroizeOnDrop.html) path.
crate_: Option<Path>,
},
}

Expand Down Expand Up @@ -340,6 +344,8 @@ impl Deref for DeriveTrait {
PartialOrd => &Trait::PartialOrd,
#[cfg(feature = "zeroize")]
Zeroize { .. } => &Trait::Zeroize,
#[cfg(feature = "zeroize")]
ZeroizeOnDrop { .. } => &Trait::ZeroizeOnDrop,
}
}
}
Expand Down Expand Up @@ -421,6 +427,16 @@ impl DeriveTrait {
util::path_from_strs(&["zeroize", "Zeroize"])
}
}
#[cfg(feature = "zeroize")]
ZeroizeOnDrop { crate_, .. } => {
if let Some(crate_) = crate_ {
let mut crate_ = crate_.clone();
crate_.segments.push(util::path_segment("ZeroizeOnDrop"));
crate_
} else {
util::path_from_strs(&["zeroize", "ZeroizeOnDrop"])
}
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,8 @@ impl Error {
"PartialOrd",
#[cfg(feature = "zeroize")]
"Zeroize",
#[cfg(feature = "zeroize")]
"ZeroizeOnDrop",
]
.join(", ")
}
Expand Down
9 changes: 5 additions & 4 deletions src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,11 @@ impl<'a> Input<'a> {
#[cfg(feature = "zeroize")]
{
// `Zeroize(crate = "..")` is used.
if let DeriveTrait::Zeroize {
crate_: Some(_), ..
} = **trait_
{
if let DeriveTrait::Zeroize { crate_: Some(_) } = **trait_ {
continue;
}
// `ZeroizeOnDrop(crate = "..")` is used.
if let DeriveTrait::ZeroizeOnDrop { crate_: Some(_) } = **trait_ {
continue;
}
// `Zeroize(fqs)` is used on any field.
Expand Down
Loading

0 comments on commit 9d05a78

Please sign in to comment.