@@ -14,54 +14,26 @@ use synstructure::{decl_derive, BindStyle};
14
14
const ZEROIZE_ATTR : & str = "zeroize" ;
15
15
16
16
/// Custom derive for `Zeroize`
17
- fn zeroize_derive ( mut s : synstructure:: Structure ) -> TokenStream {
18
- s. bind_with ( |_| BindStyle :: RefMut ) ;
19
-
17
+ fn derive_zeroize ( s : synstructure:: Structure ) -> TokenStream {
20
18
let attributes = ZeroizeDeriveAttrs :: parse ( & s) ;
21
19
22
- let zeroizers = s. each ( |bi| quote ! { #bi. zeroize( ) ; } ) ;
23
-
24
- let zeroize_impl = s. bound_impl (
25
- quote ! ( zeroize:: Zeroize ) ,
26
- quote ! {
27
- fn zeroize( & mut self ) {
28
- match self {
29
- #zeroizers
30
- }
31
- }
32
- } ,
33
- ) ;
34
-
35
- if attributes. no_drop {
36
- return zeroize_impl;
37
- }
38
-
39
- let drop_impl = s. gen_impl ( quote ! {
40
- gen impl Drop for @Self {
41
- fn drop( & mut self ) {
42
- self . zeroize( ) ;
43
- }
44
- }
45
- } ) ;
46
-
47
- quote ! {
48
- #zeroize_impl
49
-
50
- #[ doc( hidden) ]
51
- #drop_impl
20
+ match attributes. drop {
21
+ Some ( true ) => derive_zeroize_with_drop ( s) ,
22
+ Some ( false ) => derive_zeroize_without_drop ( s) ,
23
+ None => panic ! ( "must specify either zeroize(drop) or zeroize(no_drop) attribute" ) ,
52
24
}
53
25
}
54
- decl_derive ! ( [ Zeroize , attributes( zeroize) ] => zeroize_derive ) ;
26
+ decl_derive ! ( [ Zeroize , attributes( zeroize) ] => derive_zeroize ) ;
55
27
56
28
/// Custom derive attributes for `Zeroize`
57
29
struct ZeroizeDeriveAttrs {
58
- /// Disable the on-by-default `Drop` derive
59
- no_drop : bool ,
30
+ /// Derive a `Drop` impl which calls zeroize on this type
31
+ drop : Option < bool > ,
60
32
}
61
33
62
34
impl Default for ZeroizeDeriveAttrs {
63
35
fn default ( ) -> Self {
64
- Self { no_drop : false }
36
+ Self { drop : None }
65
37
}
66
38
}
67
39
@@ -75,8 +47,8 @@ impl ZeroizeDeriveAttrs {
75
47
if attr. path . is_ident ( ZEROIZE_ATTR ) {
76
48
// TODO(tarcieri): hax, but probably good enough for now
77
49
match attr. tts . to_string ( ) . as_ref ( ) {
78
- "( drop )" => ( ) , // enabled by default
79
- "( no_drop )" => result. no_drop = true ,
50
+ "( drop )" => result . drop = Some ( true ) ,
51
+ "( no_drop )" => result. drop = Some ( false ) ,
80
52
other => panic ! ( "unknown zeroize attribute: {}" , other) ,
81
53
}
82
54
}
@@ -87,15 +59,89 @@ impl ZeroizeDeriveAttrs {
87
59
}
88
60
}
89
61
62
+ /// Custom derive for `Zeroize` (without `Drop`)
63
+ fn derive_zeroize_without_drop ( mut s : synstructure:: Structure ) -> TokenStream {
64
+ s. bind_with ( |_| BindStyle :: RefMut ) ;
65
+
66
+ let zeroizers = s. each ( |bi| quote ! { #bi. zeroize( ) ; } ) ;
67
+
68
+ s. bound_impl (
69
+ quote ! ( zeroize:: Zeroize ) ,
70
+ quote ! {
71
+ fn zeroize( & mut self ) {
72
+ match self {
73
+ #zeroizers
74
+ }
75
+ }
76
+ } ,
77
+ )
78
+ }
79
+
80
+ /// Custom derive for `Zeroize` and `Drop`
81
+ fn derive_zeroize_with_drop ( s : synstructure:: Structure ) -> TokenStream {
82
+ let drop_impl = s. gen_impl ( quote ! {
83
+ gen impl Drop for @Self {
84
+ fn drop( & mut self ) {
85
+ self . zeroize( ) ;
86
+ }
87
+ }
88
+ } ) ;
89
+
90
+ let zeroize_impl = derive_zeroize_without_drop ( s) ;
91
+
92
+ quote ! {
93
+ #zeroize_impl
94
+
95
+ #[ doc( hidden) ]
96
+ #drop_impl
97
+ }
98
+ }
99
+
90
100
#[ cfg( test) ]
91
101
mod tests {
92
102
use super :: * ;
93
103
use synstructure:: test_derive;
94
104
95
105
#[ test]
96
- fn zeroize ( ) {
106
+ fn zeroize_without_drop ( ) {
107
+ test_derive ! {
108
+ derive_zeroize_without_drop {
109
+ struct Z {
110
+ a: String ,
111
+ b: Vec <u8 >,
112
+ c: [ u8 ; 3 ] ,
113
+ }
114
+ }
115
+ expands to {
116
+ #[ allow( non_upper_case_globals) ]
117
+ #[ doc( hidden) ]
118
+ const _DERIVE_zeroize_Zeroize_FOR_Z: ( ) = {
119
+ extern crate zeroize;
120
+ impl zeroize:: Zeroize for Z {
121
+ fn zeroize( & mut self ) {
122
+ match self {
123
+ Z {
124
+ a: ref mut __binding_0,
125
+ b: ref mut __binding_1,
126
+ c: ref mut __binding_2,
127
+ } => {
128
+ { __binding_0. zeroize( ) ; }
129
+ { __binding_1. zeroize( ) ; }
130
+ { __binding_2. zeroize( ) ; }
131
+ }
132
+ }
133
+ }
134
+ }
135
+ } ;
136
+ }
137
+ no_build // tests the code compiles are in the `zeroize` crate
138
+ }
139
+ }
140
+
141
+ #[ test]
142
+ fn zeroize_with_drop ( ) {
97
143
test_derive ! {
98
- zeroize_derive {
144
+ derive_zeroize_with_drop {
99
145
struct Z {
100
146
a: String ,
101
147
b: Vec <u8 >,
0 commit comments