@@ -8,6 +8,52 @@ use crate::inflate::core::{decompress, inflate_flags, DecompressorOxide, TINFL_L
8
8
use crate :: inflate:: TINFLStatus ;
9
9
use crate :: { DataFormat , MZError , MZFlush , MZResult , MZStatus , StreamResult } ;
10
10
11
+ /// Tag that determines reset policy of [InflateState](struct.InflateState.html)
12
+ pub trait ResetPolicy {
13
+ /// Performs reset
14
+ fn reset ( & self , state : & mut InflateState ) ;
15
+ }
16
+
17
+ /// Resets state, without performing expensive ops (e.g. zeroing buffer)
18
+ ///
19
+ /// Note that not zeroing buffer can lead to security issues when dealing with untrusted input.
20
+ pub struct MinReset ;
21
+
22
+ impl ResetPolicy for MinReset {
23
+ fn reset ( & self , state : & mut InflateState ) {
24
+ state. decompressor ( ) . init ( ) ;
25
+ state. dict_ofs = 0 ;
26
+ state. dict_avail = 0 ;
27
+ state. first_call = true ;
28
+ state. has_flushed = false ;
29
+ state. last_status = TINFLStatus :: NeedsMoreInput ;
30
+ }
31
+ }
32
+
33
+ /// Resets state and zero memory, continuing to use the same data format.
34
+ pub struct ZeroReset ;
35
+
36
+ impl ResetPolicy for ZeroReset {
37
+ #[ inline]
38
+ fn reset ( & self , state : & mut InflateState ) {
39
+ MinReset . reset ( state) ;
40
+ state. dict = [ 0 ; TINFL_LZ_DICT_SIZE ] ;
41
+ }
42
+ }
43
+
44
+ /// Full reset of the state, including zeroing memory.
45
+ ///
46
+ /// Requires to provide new data format.
47
+ pub struct FullReset ( DataFormat ) ;
48
+
49
+ impl ResetPolicy for FullReset {
50
+ #[ inline]
51
+ fn reset ( & self , state : & mut InflateState ) {
52
+ ZeroReset . reset ( state) ;
53
+ state. data_format = self . 0 ;
54
+ }
55
+ }
56
+
11
57
/// A struct that compbines a decompressor with extra data for streaming decompression.
12
58
///
13
59
pub struct InflateState {
@@ -95,17 +141,17 @@ impl InflateState {
95
141
b
96
142
}
97
143
144
+ #[ inline]
98
145
/// Reset the decompressor without re-allocating memory, using the given
99
146
/// data format.
100
147
pub fn reset ( & mut self , data_format : DataFormat ) {
101
- self . decompressor ( ) . init ( ) ;
102
- self . dict = [ 0 ; TINFL_LZ_DICT_SIZE ] ;
103
- self . dict_ofs = 0 ;
104
- self . dict_avail = 0 ;
105
- self . first_call = true ;
106
- self . has_flushed = false ;
107
- self . data_format = data_format;
108
- self . last_status = TINFLStatus :: NeedsMoreInput ;
148
+ self . reset_as ( FullReset ( data_format) ) ;
149
+ }
150
+
151
+ #[ inline]
152
+ /// Resets the state according to specified policy.
153
+ pub fn reset_as < T : ResetPolicy > ( & mut self , policy : T ) {
154
+ policy. reset ( self )
109
155
}
110
156
}
111
157
@@ -314,7 +360,17 @@ mod test {
314
360
assert_eq ! ( out[ ..res. bytes_written as usize ] , b"Hello, zlib!" [ ..] ) ;
315
361
assert_eq ! ( res. bytes_consumed, encoded. len( ) ) ;
316
362
317
- state. reset ( DataFormat :: Zlib ) ;
363
+ state. reset_as ( super :: ZeroReset ) ;
364
+ out. iter_mut ( ) . map ( |x| * x = 0 ) . count ( ) ;
365
+ let res = inflate ( & mut state, & encoded, & mut out, MZFlush :: Finish ) ;
366
+ let status = res. status . expect ( "Failed to decompress!" ) ;
367
+ assert_eq ! ( status, MZStatus :: StreamEnd ) ;
368
+ assert_eq ! ( out[ ..res. bytes_written as usize ] , b"Hello, zlib!" [ ..] ) ;
369
+ assert_eq ! ( res. bytes_consumed, encoded. len( ) ) ;
370
+
371
+ state. reset_as ( super :: MinReset ) ;
372
+ out. iter_mut ( ) . map ( |x| * x = 0 ) . count ( ) ;
373
+ let res = inflate ( & mut state, & encoded, & mut out, MZFlush :: Finish ) ;
318
374
let status = res. status . expect ( "Failed to decompress!" ) ;
319
375
assert_eq ! ( status, MZStatus :: StreamEnd ) ;
320
376
assert_eq ! ( out[ ..res. bytes_written as usize ] , b"Hello, zlib!" [ ..] ) ;
0 commit comments