@@ -103,6 +103,7 @@ pub struct Decompressor {
103
103
queued_rle : Option < ( u8 , usize ) > ,
104
104
queued_backref : Option < ( usize , usize ) > ,
105
105
last_block : bool ,
106
+ fixed_table : bool ,
106
107
107
108
state : State ,
108
109
checksum : Adler32 ,
@@ -145,6 +146,7 @@ impl Decompressor {
145
146
state : State :: ZlibHeader ,
146
147
last_block : false ,
147
148
ignore_adler32 : false ,
149
+ fixed_table : false ,
148
150
}
149
151
}
150
152
@@ -182,7 +184,7 @@ impl Decompressor {
182
184
183
185
fn read_block_header ( & mut self , remaining_input : & mut & [ u8 ] ) -> Result < ( ) , DecompressionError > {
184
186
self . fill_buffer ( remaining_input) ;
185
- if self . nbits < 3 {
187
+ if self . nbits < 10 {
186
188
return Ok ( ( ) ) ;
187
189
}
188
190
@@ -209,8 +211,35 @@ impl Decompressor {
209
211
}
210
212
0b01 => {
211
213
self . consume_bits ( 3 ) ;
212
- // TODO: Do this statically rather than every time.
213
- Self :: build_tables ( 288 , & FIXED_CODE_LENGTHS , & mut self . compression ) ?;
214
+
215
+ // Check for an entirely empty blocks which can happen if there are "partial
216
+ // flushes" in the deflate stream. With fixed huffman codes, the EOF symbol is
217
+ // 7-bits of zeros so we peak ahead and see if the next 7-bits are all zero.
218
+ if self . peak_bits ( 7 ) == 0 {
219
+ self . consume_bits ( 7 ) ;
220
+ if self . last_block {
221
+ self . state = State :: Checksum ;
222
+ return Ok ( ( ) ) ;
223
+ }
224
+
225
+ // At this point we've consumed the entire block and need to read the next block
226
+ // header. If tail call optimization were guaranteed, we could just recurse
227
+ // here. But without it, a long sequence of empty fixed-blocks might cause a
228
+ // stack overflow. Instead, we consume all empty blocks in a loop and then
229
+ // recurse. This is the only recursive call this function, and thus is safe.
230
+ while self . nbits >= 10 && self . peak_bits ( 10 ) == 0b010 {
231
+ self . consume_bits ( 10 ) ;
232
+ self . fill_buffer ( remaining_input) ;
233
+ }
234
+ return self . read_block_header ( remaining_input) ;
235
+ }
236
+
237
+ // Build decoding tables if the previous block wasn't also a fixed block.
238
+ if !self . fixed_table {
239
+ self . fixed_table = true ;
240
+ Self :: build_tables ( 288 , & FIXED_CODE_LENGTHS , & mut self . compression ) ?;
241
+ }
242
+
214
243
self . state = State :: CompressedData ;
215
244
Ok ( ( ) )
216
245
}
@@ -231,6 +260,7 @@ impl Decompressor {
231
260
232
261
self . consume_bits ( 17 ) ;
233
262
self . state = State :: CodeLengthCodes ;
263
+ self . fixed_table = false ;
234
264
Ok ( ( ) )
235
265
}
236
266
0b11 => Err ( DecompressionError :: InvalidBlockType ) ,
0 commit comments