| ... | @@ -58,8 +58,10 @@ const Huffman = struct { | ... | @@ -58,8 +58,10 @@ const Huffman = struct { |
| 58 | } | 58 | } |
| 59 | | 59 | |
| 60 | // All zero. | 60 | // All zero. |
| 61 | if (self.count[0] == code_length.len) | 61 | if (self.count[0] == code_length.len) { |
| | 62 | self.min_code_len = 0; |
| 62 | return; | 63 | return; |
| | 64 | } |
| 63 | | 65 | |
| 64 | var left: isize = 1; | 66 | var left: isize = 1; |
| 65 | for (self.count[1..]) |val| { | 67 | for (self.count[1..]) |val| { |
| ... | @@ -280,7 +282,7 @@ pub fn InflateStream(comptime ReaderType: type) type { | ... | @@ -280,7 +282,7 @@ pub fn InflateStream(comptime ReaderType: type) type { |
| 280 | return self.bits & mask; | 282 | return self.bits & mask; |
| 281 | } | 283 | } |
| 282 | fn readBits(self: *Self, bits: usize) !u32 { | 284 | fn readBits(self: *Self, bits: usize) !u32 { |
| 283 | const val = self.peekBits(bits); | 285 | const val = try self.peekBits(bits); |
| 284 | self.discardBits(bits); | 286 | self.discardBits(bits); |
| 285 | return val; | 287 | return val; |
| 286 | } | 288 | } |
| ... | @@ -487,6 +489,8 @@ pub fn InflateStream(comptime ReaderType: type) type { | ... | @@ -487,6 +489,8 @@ pub fn InflateStream(comptime ReaderType: type) type { |
| 487 | // We can't read PREFIX_LUT_BITS as we don't want to read past the | 489 | // We can't read PREFIX_LUT_BITS as we don't want to read past the |
| 488 | // deflate stream end, use an incremental approach instead. | 490 | // deflate stream end, use an incremental approach instead. |
| 489 | var code_len = h.min_code_len; | 491 | var code_len = h.min_code_len; |
| | 492 | if (code_len == 0) |
| | 493 | return error.OutOfCodes; |
| 490 | while (true) { | 494 | while (true) { |
| 491 | _ = try self.peekBits(code_len); | 495 | _ = try self.peekBits(code_len); |
| 492 | // Small optimization win, use as many bits as possible in the | 496 | // Small optimization win, use as many bits as possible in the |
| ... | @@ -658,11 +662,27 @@ test "lengths overflow" { | ... | @@ -658,11 +662,27 @@ test "lengths overflow" { |
| 658 | // f dy hlit hdist hclen 16 17 18 0 (18) x138 (18) x138 (18) x39 (16) x6 | 662 | // f dy hlit hdist hclen 16 17 18 0 (18) x138 (18) x138 (18) x39 (16) x6 |
| 659 | // 1 10 11101 11101 0000 010 010 010 010 (11) 1111111 (11) 1111111 (11) 0011100 (01) 11 | 663 | // 1 10 11101 11101 0000 010 010 010 010 (11) 1111111 (11) 1111111 (11) 0011100 (01) 11 |
| 660 | const stream = [_]u8{ 0b11101101, 0b00011101, 0b00100100, 0b11101001, 0b11111111, 0b11111111, 0b00111001, 0b00001110 }; | 664 | 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 | } |
| 661 | | 675 | |
| 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("\x950000")); |
| | 679 | try std.testing.expectError(error.OutOfCodes, testInflate("\x950\x00\x0000000")); |
| | 680 | } |
| | 681 | |
| | 682 | fn testInflate(data: []const u8) !void { |
| 663 | var window: [0x8000]u8 = undefined; | 683 | var window: [0x8000]u8 = undefined; |
| | 684 | const reader = std.io.fixedBufferStream(data).reader(); |
| 664 | var inflate = inflateStream(reader, &window); | 685 | var inflate = inflateStream(reader, &window); |
| 665 | | 686 | var inflated = try inflate.reader().readAllAlloc(std.testing.allocator, std.math.maxInt(usize)); |
| 666 | var buf: [1]u8 = undefined; | 687 | defer std.testing.allocator.free(inflated); |
| 667 | try std.testing.expectError(error.InvalidLength, inflate.read(&buf)); | | |
| 668 | } | 688 | } |