Commit 6de2310035

Igor Anić <igor.anic@gmail.com>
2025-08-07 23:40:08
flate change bit reader Bits to usize (#24719)
Don't see why byte returned from specialPeek needs to be shifted by remaining_needed_bits. I believe that decision in specialPeek should be done on the number of the remaining bits not of the content of that bits. Some test result are changed, but they are now consistent with the original state as found in: https://github.com/ziglang/zig/blame/5f790464b0d5da3c4c1a7252643e7cdd4c4b605e/lib/std/compress/flate/Decompress.zig Changing Bits from usize to u32 or u64 now returns same results. * flate: simplify peekBitsEnding `peekBits` returns at most asked number of bits. Fails with EndOfStream when there are no available bits. If there are less bits available than asked still returns that available bits. Hopefully this change better reflects intention. On first input stream peek error we break the loop.
1 parent 8843631
Changed files (1)
lib
std
compress
lib/std/compress/flate/Decompress.zig
@@ -25,8 +25,7 @@ state: State,
 
 err: ?Error,
 
-/// TODO: change this to usize
-const Bits = u64;
+const Bits = usize;
 
 const BlockType = enum(u2) {
     stored = 0,
@@ -550,29 +549,19 @@ fn peekBitsEnding(d: *Decompress, comptime U: type) !U {
     var u: Bits = 0;
     var remaining_needed_bits = @bitSizeOf(U) - remaining_bits;
     var i: usize = 0;
-    while (remaining_needed_bits >= 8) {
-        const byte = try specialPeek(in, next_bits, i);
-        u |= @as(Bits, byte) << @intCast(i * 8);
-        remaining_needed_bits -= 8;
+    while (remaining_needed_bits > 0) {
+        const peeked = in.peek(i + 1) catch |err| switch (err) {
+            error.ReadFailed => return error.ReadFailed,
+            error.EndOfStream => break,
+        };
+        u |= @as(Bits, peeked[i]) << @intCast(i * 8);
+        remaining_needed_bits -|= 8;
         i += 1;
     }
-    if (remaining_needed_bits != 0) {
-        const byte = try specialPeek(in, next_bits, i);
-        u |= @as(Bits, byte) << @intCast((i * 8) + remaining_needed_bits);
-    }
+    if (remaining_bits == 0 and i == 0) return error.EndOfStream;
     return @truncate((u << remaining_bits) | next_bits);
 }
 
-/// If there is any unconsumed data, handles EndOfStream by pretending there
-/// are zeroes afterwards.
-fn specialPeek(in: *Reader, next_bits: Bits, i: usize) Reader.Error!u8 {
-    const peeked = in.peek(i + 1) catch |err| switch (err) {
-        error.ReadFailed => return error.ReadFailed,
-        error.EndOfStream => if (next_bits == 0 and i == 0) return error.EndOfStream else return 0,
-    };
-    return peeked[i];
-}
-
 fn tossBits(d: *Decompress, n: u4) !void {
     const remaining_bits = d.remaining_bits;
     const next_bits = d.next_bits;
@@ -1032,7 +1021,7 @@ test "failing invalid-tree01" {
     try testFailure(.raw, @embedFile("testdata/fuzz/invalid-tree01.input"), error.IncompleteHuffmanTree);
 }
 test "failing invalid-tree02" {
-    try testFailure(.raw, @embedFile("testdata/fuzz/invalid-tree02.input"), error.EndOfStream);
+    try testFailure(.raw, @embedFile("testdata/fuzz/invalid-tree02.input"), error.IncompleteHuffmanTree);
 }
 test "failing invalid-tree03" {
     try testFailure(.raw, @embedFile("testdata/fuzz/invalid-tree03.input"), error.IncompleteHuffmanTree);
@@ -1065,7 +1054,7 @@ test "failing puff10" {
     try testFailure(.raw, @embedFile("testdata/fuzz/puff10.input"), error.InvalidCode);
 }
 test "failing puff11" {
-    try testFailure(.raw, @embedFile("testdata/fuzz/puff11.input"), error.EndOfStream);
+    try testFailure(.raw, @embedFile("testdata/fuzz/puff11.input"), error.InvalidMatch);
 }
 test "failing puff12" {
     try testFailure(.raw, @embedFile("testdata/fuzz/puff12.input"), error.InvalidDynamicBlockHeader);
@@ -1137,7 +1126,7 @@ test "deflate-stream" {
 }
 
 test "empty-distance-alphabet01" {
-    try testFailure(.raw, @embedFile("testdata/fuzz/empty-distance-alphabet01.input"), error.EndOfStream);
+    try testDecompress(.raw, @embedFile("testdata/fuzz/empty-distance-alphabet01.input"), "");
 }
 
 test "empty-distance-alphabet02" {