| ... | @@ -25,8 +25,7 @@ state: State, | ... | @@ -25,8 +25,7 @@ state: State, |
| 25 | | 25 | |
| 26 | err: ?Error, | 26 | err: ?Error, |
| 27 | | 27 | |
| 28 | /// TODO: change this to usize | 28 | const Bits = usize; |
| 29 | const Bits = u64; | | |
| 30 | | 29 | |
| 31 | const BlockType = enum(u2) { | 30 | const BlockType = enum(u2) { |
| 32 | stored = 0, | 31 | stored = 0, |
| ... | @@ -550,29 +549,19 @@ fn peekBitsEnding(d: *Decompress, comptime U: type) !U { | ... | @@ -550,29 +549,19 @@ fn peekBitsEnding(d: *Decompress, comptime U: type) !U { |
| 550 | var u: Bits = 0; | 549 | var u: Bits = 0; |
| 551 | var remaining_needed_bits = @bitSizeOf(U) - remaining_bits; | 550 | var remaining_needed_bits = @bitSizeOf(U) - remaining_bits; |
| 552 | var i: usize = 0; | 551 | var i: usize = 0; |
| 553 | while (remaining_needed_bits >= 8) { | 552 | while (remaining_needed_bits > 0) { |
| 554 | const byte = try specialPeek(in, next_bits, i); | 553 | const peeked = in.peek(i + 1) catch |err| switch (err) { |
| 555 | u |= @as(Bits, byte) << @intCast(i * 8); | 554 | error.ReadFailed => return error.ReadFailed, |
| 556 | remaining_needed_bits -= 8; | 555 | error.EndOfStream => break, |
| | 556 | }; |
| | 557 | u |= @as(Bits, peeked[i]) << @intCast(i * 8); |
| | 558 | remaining_needed_bits -|= 8; |
| 557 | i += 1; | 559 | i += 1; |
| 558 | } | 560 | } |
| 559 | if (remaining_needed_bits != 0) { | 561 | if (remaining_bits == 0 and i == 0) return error.EndOfStream; |
| 560 | const byte = try specialPeek(in, next_bits, i); | | |
| 561 | u |= @as(Bits, byte) << @intCast((i * 8) + remaining_needed_bits); | | |
| 562 | } | | |
| 563 | return @truncate((u << remaining_bits) | next_bits); | 562 | return @truncate((u << remaining_bits) | next_bits); |
| 564 | } | 563 | } |
| 565 | | 564 | |
| 566 | /// If there is any unconsumed data, handles EndOfStream by pretending there | | |
| 567 | /// are zeroes afterwards. | | |
| 568 | fn specialPeek(in: *Reader, next_bits: Bits, i: usize) Reader.Error!u8 { | | |
| 569 | const peeked = in.peek(i + 1) catch |err| switch (err) { | | |
| 570 | error.ReadFailed => return error.ReadFailed, | | |
| 571 | error.EndOfStream => if (next_bits == 0 and i == 0) return error.EndOfStream else return 0, | | |
| 572 | }; | | |
| 573 | return peeked[i]; | | |
| 574 | } | | |
| 575 | | | |
| 576 | fn tossBits(d: *Decompress, n: u4) !void { | 565 | fn tossBits(d: *Decompress, n: u4) !void { |
| 577 | const remaining_bits = d.remaining_bits; | 566 | const remaining_bits = d.remaining_bits; |
| 578 | const next_bits = d.next_bits; | 567 | const next_bits = d.next_bits; |
| ... | @@ -1032,7 +1021,7 @@ test "failing invalid-tree01" { | ... | @@ -1032,7 +1021,7 @@ test "failing invalid-tree01" { |
| 1032 | try testFailure(.raw, @embedFile("testdata/fuzz/invalid-tree01.input"), error.IncompleteHuffmanTree); | 1021 | try testFailure(.raw, @embedFile("testdata/fuzz/invalid-tree01.input"), error.IncompleteHuffmanTree); |
| 1033 | } | 1022 | } |
| 1034 | test "failing invalid-tree02" { | 1023 | test "failing invalid-tree02" { |
| 1035 | try testFailure(.raw, @embedFile("testdata/fuzz/invalid-tree02.input"), error.EndOfStream); | 1024 | try testFailure(.raw, @embedFile("testdata/fuzz/invalid-tree02.input"), error.IncompleteHuffmanTree); |
| 1036 | } | 1025 | } |
| 1037 | test "failing invalid-tree03" { | 1026 | test "failing invalid-tree03" { |
| 1038 | try testFailure(.raw, @embedFile("testdata/fuzz/invalid-tree03.input"), error.IncompleteHuffmanTree); | 1027 | try testFailure(.raw, @embedFile("testdata/fuzz/invalid-tree03.input"), error.IncompleteHuffmanTree); |
| ... | @@ -1065,7 +1054,7 @@ test "failing puff10" { | ... | @@ -1065,7 +1054,7 @@ test "failing puff10" { |
| 1065 | try testFailure(.raw, @embedFile("testdata/fuzz/puff10.input"), error.InvalidCode); | 1054 | try testFailure(.raw, @embedFile("testdata/fuzz/puff10.input"), error.InvalidCode); |
| 1066 | } | 1055 | } |
| 1067 | test "failing puff11" { | 1056 | test "failing puff11" { |
| 1068 | try testFailure(.raw, @embedFile("testdata/fuzz/puff11.input"), error.EndOfStream); | 1057 | try testFailure(.raw, @embedFile("testdata/fuzz/puff11.input"), error.InvalidMatch); |
| 1069 | } | 1058 | } |
| 1070 | test "failing puff12" { | 1059 | test "failing puff12" { |
| 1071 | try testFailure(.raw, @embedFile("testdata/fuzz/puff12.input"), error.InvalidDynamicBlockHeader); | 1060 | try testFailure(.raw, @embedFile("testdata/fuzz/puff12.input"), error.InvalidDynamicBlockHeader); |
| ... | @@ -1137,7 +1126,7 @@ test "deflate-stream" { | ... | @@ -1137,7 +1126,7 @@ test "deflate-stream" { |
| 1137 | } | 1126 | } |
| 1138 | | 1127 | |
| 1139 | test "empty-distance-alphabet01" { | 1128 | test "empty-distance-alphabet01" { |
| 1140 | try testFailure(.raw, @embedFile("testdata/fuzz/empty-distance-alphabet01.input"), error.EndOfStream); | 1129 | try testDecompress(.raw, @embedFile("testdata/fuzz/empty-distance-alphabet01.input"), ""); |
| 1141 | } | 1130 | } |
| 1142 | | 1131 | |
| 1143 | test "empty-distance-alphabet02" { | 1132 | test "empty-distance-alphabet02" { |