| ... | @@ -157,30 +157,23 @@ pub fn Inflate(comptime container: Container, comptime ReaderType: type) type { | ... | @@ -157,30 +157,23 @@ pub fn Inflate(comptime container: Container, comptime ReaderType: type) type { |
| 157 | var cl_dec: hfd.CodegenDecoder = .{}; | 157 | var cl_dec: hfd.CodegenDecoder = .{}; |
| 158 | try cl_dec.generate(&cl_lens); | 158 | try cl_dec.generate(&cl_lens); |
| 159 | | 159 | |
| 160 | // literal code lengths | 160 | // decoded code lengths |
| 161 | var lit_lens = [_]u4{0} ** (286); | 161 | var dec_lens = [_]u4{0} ** (286 + 30); |
| 162 | var pos: usize = 0; | 162 | var pos: usize = 0; |
| 163 | while (pos < hlit) { | 163 | while (pos < hlit + hdist) { |
| 164 | const sym = try cl_dec.find(try self.bits.peekF(u7, F.reverse)); | 164 | const sym = try cl_dec.find(try self.bits.peekF(u7, F.reverse)); |
| 165 | try self.bits.shift(sym.code_bits); | 165 | try self.bits.shift(sym.code_bits); |
| 166 | pos += try self.dynamicCodeLength(sym.symbol, &lit_lens, pos); | 166 | pos += try self.dynamicCodeLength(sym.symbol, &dec_lens, pos); |
| 167 | } | 167 | } |
| 168 | if (pos > hlit) | 168 | if (pos > hlit + hdist) { |
| 169 | return error.InvalidDynamicBlockHeader; | 169 | return error.InvalidDynamicBlockHeader; |
| 170 | | | |
| 171 | // distance code lenths | | |
| 172 | var dst_lens = [_]u4{0} ** (30); | | |
| 173 | pos = 0; | | |
| 174 | while (pos < hdist) { | | |
| 175 | const sym = try cl_dec.find(try self.bits.peekF(u7, F.reverse)); | | |
| 176 | try self.bits.shift(sym.code_bits); | | |
| 177 | pos += try self.dynamicCodeLength(sym.symbol, &dst_lens, pos); | | |
| 178 | } | 170 | } |
| 179 | if (pos > hdist) | | |
| 180 | return error.InvalidDynamicBlockHeader; | | |
| 181 | | 171 | |
| 182 | try self.lit_dec.generate(&lit_lens); | 172 | // literal code lengts to literal decoder |
| 183 | try self.dst_dec.generate(&dst_lens); | 173 | try self.lit_dec.generate(dec_lens[0..hlit]); |
| | 174 | |
| | 175 | // distance code lengths to distance decoder |
| | 176 | try self.dst_dec.generate(dec_lens[hlit .. hlit + hdist]); |
| 184 | } | 177 | } |
| 185 | | 178 | |
| 186 | // Decode code length symbol to code length. Writes decoded length into | 179 | // Decode code length symbol to code length. Writes decoded length into |
| ... | @@ -496,7 +489,7 @@ test "flate.Inflate fuzzing tests" { | ... | @@ -496,7 +489,7 @@ test "flate.Inflate fuzzing tests" { |
| 496 | .{ .input = "puff14", .err = error.EndOfStream }, | 489 | .{ .input = "puff14", .err = error.EndOfStream }, |
| 497 | .{ .input = "puff15", .err = error.IncompleteHuffmanTree }, | 490 | .{ .input = "puff15", .err = error.IncompleteHuffmanTree }, |
| 498 | .{ .input = "puff16", .err = error.InvalidDynamicBlockHeader }, | 491 | .{ .input = "puff16", .err = error.InvalidDynamicBlockHeader }, |
| 499 | .{ .input = "puff17", .err = error.InvalidDynamicBlockHeader }, // 25 | 492 | .{ .input = "puff17", .err = error.MissingEndOfBlockCode }, // 25 |
| 500 | .{ .input = "fuzz1", .err = error.InvalidDynamicBlockHeader }, | 493 | .{ .input = "fuzz1", .err = error.InvalidDynamicBlockHeader }, |
| 501 | .{ .input = "fuzz2", .err = error.InvalidDynamicBlockHeader }, | 494 | .{ .input = "fuzz2", .err = error.InvalidDynamicBlockHeader }, |
| 502 | .{ .input = "fuzz3", .err = error.InvalidMatch }, | 495 | .{ .input = "fuzz3", .err = error.InvalidMatch }, |
| ... | @@ -506,8 +499,8 @@ test "flate.Inflate fuzzing tests" { | ... | @@ -506,8 +499,8 @@ test "flate.Inflate fuzzing tests" { |
| 506 | .{ .input = "puff20", .err = error.OversubscribedHuffmanTree }, | 499 | .{ .input = "puff20", .err = error.OversubscribedHuffmanTree }, |
| 507 | .{ .input = "puff21", .err = error.OversubscribedHuffmanTree }, | 500 | .{ .input = "puff21", .err = error.OversubscribedHuffmanTree }, |
| 508 | .{ .input = "puff22", .err = error.OversubscribedHuffmanTree }, | 501 | .{ .input = "puff22", .err = error.OversubscribedHuffmanTree }, |
| 509 | .{ .input = "puff23", .err = error.InvalidDynamicBlockHeader }, // 35 | 502 | .{ .input = "puff23", .err = error.OversubscribedHuffmanTree }, // 35 |
| 510 | .{ .input = "puff24", .err = error.InvalidDynamicBlockHeader }, | 503 | .{ .input = "puff24", .err = error.IncompleteHuffmanTree }, |
| 511 | .{ .input = "puff25", .err = error.OversubscribedHuffmanTree }, | 504 | .{ .input = "puff25", .err = error.OversubscribedHuffmanTree }, |
| 512 | .{ .input = "puff26", .err = error.InvalidDynamicBlockHeader }, | 505 | .{ .input = "puff26", .err = error.InvalidDynamicBlockHeader }, |
| 513 | .{ .input = "puff27", .err = error.InvalidDynamicBlockHeader }, | 506 | .{ .input = "puff27", .err = error.InvalidDynamicBlockHeader }, |
| ... | @@ -527,3 +520,15 @@ test "flate.Inflate fuzzing tests" { | ... | @@ -527,3 +520,15 @@ test "flate.Inflate fuzzing tests" { |
| 527 | } | 520 | } |
| 528 | } | 521 | } |
| 529 | } | 522 | } |
| | 523 | |
| | 524 | test "flate bug 18966" { |
| | 525 | const input = @embedFile("testdata/fuzz/bug_18966.input"); |
| | 526 | const expect = @embedFile("testdata/fuzz/bug_18966.expect"); |
| | 527 | |
| | 528 | var in = std.io.fixedBufferStream(input); |
| | 529 | var out = std.ArrayList(u8).init(testing.allocator); |
| | 530 | defer out.deinit(); |
| | 531 | |
| | 532 | try decompress(.gzip, in.reader(), out.writer()); |
| | 533 | try testing.expectEqualStrings(expect, out.items); |
| | 534 | } |