authorgravatar for fncontroloption@noreply.codeberg.orgFnControlOption <fncontroloption@noreply.codeberg.org> 2023-01-25 08:43:13-08:00
committergravatar for fncontroloption@noreply.codeberg.orgFnControlOption <fncontroloption@noreply.codeberg.org> 2023-01-25 08:49:59-08:00
logd0dedefde97aef61db31de6f0cd66846082720d6
treee7c2265aab3f350841abe792e3b80b4d5bc53bc4
parent92ea7bce5dc31f0abbf9dcfcb9b0b749e604bba9

std.compress.xz: fix for big-endian targets


2 files changed, 43 insertions(+), 40 deletions(-)

lib/std/compress/xz.zig+42-39
...@@ -3,25 +3,6 @@ const block = @import("xz/block.zig");...@@ -3,25 +3,6 @@ const block = @import("xz/block.zig");
3const Allocator = std.mem.Allocator;3const Allocator = std.mem.Allocator;
4const Crc32 = std.hash.Crc32;4const Crc32 = std.hash.Crc32;
55
6pub const Flags = packed struct(u16) {
7 reserved1: u8,
8 check_kind: Check,
9 reserved2: u4,
10};
11
12pub const Header = extern struct {
13 magic: [6]u8,
14 flags: Flags,
15 crc32: u32,
16};
17
18pub const Footer = extern struct {
19 crc32: u32,
20 backward_size: u32,
21 flags: Flags,
22 magic: [2]u8,
23};
24
25pub const Check = enum(u4) {6pub const Check = enum(u4) {
26 none = 0x00,7 none = 0x00,
27 crc32 = 0x01,8 crc32 = 0x01,
...@@ -30,6 +11,20 @@ pub const Check = enum(u4) {...@@ -30,6 +11,20 @@ pub const Check = enum(u4) {
30 _,11 _,
31};12};
3213
14fn readStreamFlags(reader: anytype, check: *Check) !void {
15 var bit_reader = std.io.bitReader(.Little, reader);
16
17 const reserved1 = try bit_reader.readBitsNoEof(u8, 8);
18 if (reserved1 != 0)
19 return error.CorruptInput;
20
21 check.* = @intToEnum(Check, try bit_reader.readBitsNoEof(u4, 4));
22
23 const reserved2 = try bit_reader.readBitsNoEof(u4, 4);
24 if (reserved2 != 0)
25 return error.CorruptInput;
26}
27
33pub fn decompress(allocator: Allocator, reader: anytype) !Decompress(@TypeOf(reader)) {28pub fn decompress(allocator: Allocator, reader: anytype) !Decompress(@TypeOf(reader)) {
34 return Decompress(@TypeOf(reader)).init(allocator, reader);29 return Decompress(@TypeOf(reader)).init(allocator, reader);
35}30}
...@@ -46,21 +41,24 @@ pub fn Decompress(comptime ReaderType: type) type {...@@ -46,21 +41,24 @@ pub fn Decompress(comptime ReaderType: type) type {
46 in_reader: ReaderType,41 in_reader: ReaderType,
4742
48 fn init(allocator: Allocator, source: ReaderType) !Self {43 fn init(allocator: Allocator, source: ReaderType) !Self {
49 const header = try source.readStruct(Header);44 const magic = try source.readBytesNoEof(6);
5045 if (!std.mem.eql(u8, &magic, &.{ 0xFD, '7', 'z', 'X', 'Z', 0x00 }))
51 if (!std.mem.eql(u8, &header.magic, &.{ 0xFD, '7', 'z', 'X', 'Z', 0x00 }))
52 return error.BadHeader;46 return error.BadHeader;
5347
54 if (header.flags.reserved1 != 0 or header.flags.reserved2 != 0)48 var check: Check = undefined;
55 return error.BadHeader;49 const hash_a = blk: {
50 var hasher = std.compress.hashedReader(source, Crc32.init());
51 try readStreamFlags(hasher.reader(), &check);
52 break :blk hasher.hasher.final();
53 };
5654
57 const hash = Crc32.hash(std.mem.asBytes(&header.flags));55 const hash_b = try source.readIntLittle(u32);
58 if (hash != header.crc32)56 if (hash_a != hash_b)
59 return error.WrongChecksum;57 return error.WrongChecksum;
6058
61 return Self{59 return Self{
62 .allocator = allocator,60 .allocator = allocator,
63 .block_decoder = try block.decoder(allocator, source, header.flags.check_kind),61 .block_decoder = try block.decoder(allocator, source, check),
64 .in_reader = source,62 .in_reader = source,
65 };63 };
66 }64 }
...@@ -114,22 +112,27 @@ pub fn Decompress(comptime ReaderType: type) type {...@@ -114,22 +112,27 @@ pub fn Decompress(comptime ReaderType: type) type {
114 break :blk counter.bytes_read;112 break :blk counter.bytes_read;
115 };113 };
116114
117 const footer = try self.in_reader.readStruct(Footer);115 const hash_a = try self.in_reader.readIntLittle(u32);
118 const backward_size = (footer.backward_size + 1) * 4;
119 if (backward_size != index_size)
120 return error.CorruptInput;
121116
122 if (footer.flags.reserved1 != 0 or footer.flags.reserved2 != 0)117 const hash_b = blk: {
123 return error.CorruptInput;118 var hasher = std.compress.hashedReader(self.in_reader, Crc32.init());
119 const hashed_reader = hasher.reader();
120
121 const backward_size = (try hashed_reader.readIntLittle(u32) + 1) * 4;
122 if (backward_size != index_size)
123 return error.CorruptInput;
124
125 var check: Check = undefined;
126 try readStreamFlags(hashed_reader, &check);
127
128 break :blk hasher.hasher.final();
129 };
124130
125 var hasher = Crc32.init();131 if (hash_a != hash_b)
126 hasher.update(std.mem.asBytes(&footer.backward_size));
127 hasher.update(std.mem.asBytes(&footer.flags));
128 const hash = hasher.final();
129 if (hash != footer.crc32)
130 return error.WrongChecksum;132 return error.WrongChecksum;
131133
132 if (!std.mem.eql(u8, &footer.magic, &.{ 'Y', 'Z' }))134 const magic = try self.in_reader.readBytesNoEof(2);
135 if (!std.mem.eql(u8, &magic, &.{ 'Y', 'Z' }))
133 return error.CorruptInput;136 return error.CorruptInput;
134137
135 return 0;138 return 0;
lib/std/compress/xz/block.zig+1-1
...@@ -109,7 +109,7 @@ pub fn Decoder(comptime ReaderType: type) type {...@@ -109,7 +109,7 @@ pub fn Decoder(comptime ReaderType: type) type {
109 has_unpacked_size: bool,109 has_unpacked_size: bool,
110 };110 };
111111
112 const flags = try header_reader.readStruct(Flags);112 const flags = @bitCast(Flags, try header_reader.readByte());
113 const filter_count = @as(u3, flags.last_filter_index) + 1;113 const filter_count = @as(u3, flags.last_filter_index) + 1;
114 if (filter_count > 1)114 if (filter_count > 1)
115 return error.Unsupported;115 return error.Unsupported;