@@ -14,54 +14,26 @@ use synstructure::{decl_derive, BindStyle};
1414const ZEROIZE_ATTR : & str = "zeroize" ;
1515
1616/// 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 {
2018 let attributes = ZeroizeDeriveAttrs :: parse ( & s) ;
2119
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" ) ,
5224 }
5325}
54- decl_derive ! ( [ Zeroize , attributes( zeroize) ] => zeroize_derive ) ;
26+ decl_derive ! ( [ Zeroize , attributes( zeroize) ] => derive_zeroize ) ;
5527
5628/// Custom derive attributes for `Zeroize`
5729struct 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 > ,
6032}
6133
6234impl Default for ZeroizeDeriveAttrs {
6335 fn default ( ) -> Self {
64- Self { no_drop : false }
36+ Self { drop : None }
6537 }
6638}
6739
@@ -75,8 +47,8 @@ impl ZeroizeDeriveAttrs {
7547 if attr. path . is_ident ( ZEROIZE_ATTR ) {
7648 // TODO(tarcieri): hax, but probably good enough for now
7749 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 ) ,
8052 other => panic ! ( "unknown zeroize attribute: {}" , other) ,
8153 }
8254 }
@@ -87,15 +59,89 @@ impl ZeroizeDeriveAttrs {
8759 }
8860}
8961
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+
90100#[ cfg( test) ]
91101mod tests {
92102 use super :: * ;
93103 use synstructure:: test_derive;
94104
95105 #[ 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 ( ) {
97143 test_derive ! {
98- zeroize_derive {
144+ derive_zeroize_with_drop {
99145 struct Z {
100146 a: String ,
101147 b: Vec <u8 >,
0 commit comments