| ... | @@ -44,8 +44,11 @@ pub fn GzipStream(comptime ReaderType: type) type { | ... | @@ -44,8 +44,11 @@ pub fn GzipStream(comptime ReaderType: type) type { |
| 44 | }, | 44 | }, |
| 45 | | 45 | |
| 46 | fn init(allocator: mem.Allocator, source: ReaderType) !Self { | 46 | fn init(allocator: mem.Allocator, source: ReaderType) !Self { |
| | 47 | var hasher = std.compress.hashedReader(source, std.hash.Crc32.init()); |
| | 48 | const hashed_reader = hasher.reader(); |
| | 49 | |
| 47 | // gzip header format is specified in RFC1952 | 50 | // gzip header format is specified in RFC1952 |
| 48 | const header = try source.readBytesNoEof(10); | 51 | const header = try hashed_reader.readBytesNoEof(10); |
| 49 | | 52 | |
| 50 | // Check the ID1/ID2 fields | 53 | // Check the ID1/ID2 fields |
| 51 | if (header[0] != 0x1f or header[1] != 0x8b) | 54 | if (header[0] != 0x1f or header[1] != 0x8b) |
| ... | @@ -66,31 +69,31 @@ pub fn GzipStream(comptime ReaderType: type) type { | ... | @@ -66,31 +69,31 @@ pub fn GzipStream(comptime ReaderType: type) type { |
| 66 | _ = XFL; | 69 | _ = XFL; |
| 67 | | 70 | |
| 68 | const extra = if (FLG & FEXTRA != 0) blk: { | 71 | const extra = if (FLG & FEXTRA != 0) blk: { |
| 69 | const len = try source.readIntLittle(u16); | 72 | const len = try hashed_reader.readIntLittle(u16); |
| 70 | const tmp_buf = try allocator.alloc(u8, len); | 73 | const tmp_buf = try allocator.alloc(u8, len); |
| 71 | errdefer allocator.free(tmp_buf); | 74 | errdefer allocator.free(tmp_buf); |
| 72 | | 75 | |
| 73 | try source.readNoEof(tmp_buf); | 76 | try hashed_reader.readNoEof(tmp_buf); |
| 74 | break :blk tmp_buf; | 77 | break :blk tmp_buf; |
| 75 | } else null; | 78 | } else null; |
| 76 | errdefer if (extra) |p| allocator.free(p); | 79 | errdefer if (extra) |p| allocator.free(p); |
| 77 | | 80 | |
| 78 | const filename = if (FLG & FNAME != 0) | 81 | const filename = if (FLG & FNAME != 0) |
| 79 | try source.readUntilDelimiterAlloc(allocator, 0, max_string_len) | 82 | try hashed_reader.readUntilDelimiterAlloc(allocator, 0, max_string_len) |
| 80 | else | 83 | else |
| 81 | null; | 84 | null; |
| 82 | errdefer if (filename) |p| allocator.free(p); | 85 | errdefer if (filename) |p| allocator.free(p); |
| 83 | | 86 | |
| 84 | const comment = if (FLG & FCOMMENT != 0) | 87 | const comment = if (FLG & FCOMMENT != 0) |
| 85 | try source.readUntilDelimiterAlloc(allocator, 0, max_string_len) | 88 | try hashed_reader.readUntilDelimiterAlloc(allocator, 0, max_string_len) |
| 86 | else | 89 | else |
| 87 | null; | 90 | null; |
| 88 | errdefer if (comment) |p| allocator.free(p); | 91 | errdefer if (comment) |p| allocator.free(p); |
| 89 | | 92 | |
| 90 | if (FLG & FHCRC != 0) { | 93 | if (FLG & FHCRC != 0) { |
| 91 | // TODO: Evaluate and check the header checksum. The stdlib has | 94 | const hash = try source.readIntLittle(u16); |
| 92 | // no CRC16 yet :( | 95 | if (hash != @truncate(u16, hasher.hasher.final())) |
| 93 | _ = try source.readIntLittle(u16); | 96 | return error.WrongChecksum; |
| 94 | } | 97 | } |
| 95 | | 98 | |
| 96 | return Self{ | 99 | return Self{ |
| ... | @@ -230,3 +233,16 @@ test "sanity checks" { | ... | @@ -230,3 +233,16 @@ test "sanity checks" { |
| 230 | }, ""), | 233 | }, ""), |
| 231 | ); | 234 | ); |
| 232 | } | 235 | } |
| | 236 | |
| | 237 | test "header checksum" { |
| | 238 | try testReader(&[_]u8{ |
| | 239 | // GZIP header |
| | 240 | 0x1f, 0x8b, 0x08, 0x12, 0x00, 0x09, 0x6e, 0x88, 0x00, 0xff, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x00, |
| | 241 | |
| | 242 | // header.FHCRC (should cover entire header) |
| | 243 | 0x99, 0xd6, |
| | 244 | |
| | 245 | // GZIP data |
| | 246 | 0x01, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| | 247 | }, ""); |
| | 248 | } |