@@ -58,8 +58,10 @@ const Huffman = struct {
5858 }
5959
6060 // All zero.
61- if (self .count [0 ] == code_length .len )
61+ if (self .count [0 ] == code_length .len ) {
62+ self .min_code_len = 0 ;
6263 return ;
64+ }
6365
6466 var left : isize = 1 ;
6567 for (self .count [1.. ]) | val | {
@@ -280,7 +282,7 @@ pub fn InflateStream(comptime ReaderType: type) type {
280282 return self .bits & mask ;
281283 }
282284 fn readBits (self : * Self , bits : usize ) ! u32 {
283- const val = self .peekBits (bits );
285+ const val = try self .peekBits (bits );
284286 self .discardBits (bits );
285287 return val ;
286288 }
@@ -487,6 +489,8 @@ pub fn InflateStream(comptime ReaderType: type) type {
487489 // We can't read PREFIX_LUT_BITS as we don't want to read past the
488490 // deflate stream end, use an incremental approach instead.
489491 var code_len = h .min_code_len ;
492+ if (code_len == 0 )
493+ return error .OutOfCodes ;
490494 while (true ) {
491495 _ = try self .peekBits (code_len );
492496 // Small optimization win, use as many bits as possible in the
@@ -658,11 +662,27 @@ test "lengths overflow" {
658662 // f dy hlit hdist hclen 16 17 18 0 (18) x138 (18) x138 (18) x39 (16) x6
659663 // 1 10 11101 11101 0000 010 010 010 010 (11) 1111111 (11) 1111111 (11) 0011100 (01) 11
660664 const stream = [_ ]u8 { 0b11101101 , 0b00011101 , 0b00100100 , 0b11101001 , 0b11111111 , 0b11111111 , 0b00111001 , 0b00001110 };
665+ try std .testing .expectError (error .InvalidLength , testInflate (stream [0.. ]));
666+ }
667+
668+ test "empty distance alphabet" {
669+ // dynamic block with empty distance alphabet is valid if end of data symbol is used immediately
670+ // f dy hlit hdist hclen 16 17 18 0 8 7 9 6 10 5 11 4 12 3 13 2 14 1 15 (18) x128 (18) x128 (1) ( 0) (256)
671+ // 1 10 00000 00000 1111 000 000 010 010 000 000 000 000 000 000 000 000 000 000 000 000 000 001 000 (11) 1110101 (11) 1110101 (0) (10) (0)
672+ const stream = [_ ]u8 { 0b00000101 , 0b11100000 , 0b00000001 , 0b00001001 , 0b00000000 , 0b00000000 , 0b00000000 , 0b00000000 , 0b00010000 , 0b01011100 , 0b10111111 , 0b00101110 };
673+ try testInflate (stream [0.. ]);
674+ }
661675
662- const reader = std .io .fixedBufferStream (& stream ).reader ();
676+ test "inflateStream fuzzing" {
677+ // see https://github.com/ziglang/zig/issues/9842
678+ try std .testing .expectError (error .EndOfStream , testInflate ("\x95 0000" ));
679+ try std .testing .expectError (error .OutOfCodes , testInflate ("\x95 0\x00\x00 00000" ));
680+ }
681+
682+ fn testInflate (data : []const u8 ) ! void {
663683 var window : [0x8000 ]u8 = undefined ;
684+ const reader = std .io .fixedBufferStream (data ).reader ();
664685 var inflate = inflateStream (reader , & window );
665-
666- var buf : [1 ]u8 = undefined ;
667- try std .testing .expectError (error .InvalidLength , inflate .read (& buf ));
686+ var inflated = try inflate .reader ().readAllAlloc (std .testing .allocator , std .math .maxInt (usize ));
687+ defer std .testing .allocator .free (inflated );
668688}
0 commit comments