| ... | ... | @@ -186,6 +186,7 @@ pub fn InflateStream(comptime ReaderType: type) type { |
| 186 | 186 | wi: usize = 0, // Write index |
| 187 | 187 | ri: usize = 0, // Read index |
| 188 | 188 | el: usize = 0, // Number of readable elements |
| 189 | total_written: usize = 0, |
| 189 | 190 | |
| 190 | 191 | fn readable(self: *WSelf) usize { |
| 191 | 192 | return self.el; |
| ... | ... | @@ -210,6 +211,7 @@ pub fn InflateStream(comptime ReaderType: type) type { |
| 210 | 211 | self.buf[self.wi] = value; |
| 211 | 212 | self.wi = (self.wi + 1) & (self.buf.len - 1); |
| 212 | 213 | self.el += 1; |
| 214 | self.total_written += 1; |
| 213 | 215 | } |
| 214 | 216 | |
| 215 | 217 | // Fill dest[] with data from the window, starting from the read |
| ... | ... | @@ -462,7 +464,7 @@ pub fn InflateStream(comptime ReaderType: type) type { |
| 462 | 464 | const distance = DISTS[distance_symbol] + |
| 463 | 465 | @intCast(u16, try self.readBits(DEXT[distance_symbol])); |
| 464 | 466 | |
| 465 | | if (distance > self.window.buf.len) |
| 467 | if (distance > self.window.buf.len or distance > self.window.total_written) |
| 466 | 468 | return error.InvalidDistance; |
| 467 | 469 | |
| 468 | 470 | const written = self.window.copyFrom(distance, length); |
| ... | ... | @@ -666,13 +668,20 @@ test "lengths overflow" { |
| 666 | 668 | } |
| 667 | 669 | |
| 668 | 670 | test "empty distance alphabet" { |
| 669 | | // dynamic block with empty distance alphabet is valid if end of data symbol is used immediately |
| 671 | // dynamic block with empty distance alphabet is valid if only literals and end of data symbol are used |
| 670 | 672 | // 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 | 673 | // 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 | 674 | const stream = [_]u8{ 0b00000101, 0b11100000, 0b00000001, 0b00001001, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00010000, 0b01011100, 0b10111111, 0b00101110 }; |
| 673 | 675 | try testInflate(stream[0..]); |
| 674 | 676 | } |
| 675 | 677 | |
| 678 | test "distance past beginning of output stream" { |
| 679 | // f fx ('A') ('B') ('C') <len=4, dist=4> (end) |
| 680 | // 1 01 (01110001) (01110010) (01110011) (0000010) (00011) (0000000) |
| 681 | const stream = [_]u8{ 0b01110011, 0b01110100, 0b01110010, 0b00000110, 0b01100001, 0b00000000 }; |
| 682 | try std.testing.expectError(error.InvalidDistance, testInflate(stream[0..])); |
| 683 | } |
| 684 | |
| 676 | 685 | test "inflateStream fuzzing" { |
| 677 | 686 | // see https://github.com/ziglang/zig/issues/9842 |
| 678 | 687 | try std.testing.expectError(error.EndOfStream, testInflate("\x950000")); |