Skip to content

Commit d0dedef

Browse files
std.compress.xz: fix for big-endian targets
1 parent 92ea7bc commit d0dedef

File tree

2 files changed

+43
-40
lines changed

2 files changed

+43
-40
lines changed

lib/std/compress/xz.zig

+42-39
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,6 @@ const block = @import("xz/block.zig");
33
const Allocator = std.mem.Allocator;
44
const Crc32 = std.hash.Crc32;
55

6-
pub const Flags = packed struct(u16) {
7-
reserved1: u8,
8-
check_kind: Check,
9-
reserved2: u4,
10-
};
11-
12-
pub const Header = extern struct {
13-
magic: [6]u8,
14-
flags: Flags,
15-
crc32: u32,
16-
};
17-
18-
pub const Footer = extern struct {
19-
crc32: u32,
20-
backward_size: u32,
21-
flags: Flags,
22-
magic: [2]u8,
23-
};
24-
256
pub const Check = enum(u4) {
267
none = 0x00,
278
crc32 = 0x01,
@@ -30,6 +11,20 @@ pub const Check = enum(u4) {
3011
_,
3112
};
3213

14+
fn 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+
3328
pub fn decompress(allocator: Allocator, reader: anytype) !Decompress(@TypeOf(reader)) {
3429
return Decompress(@TypeOf(reader)).init(allocator, reader);
3530
}
@@ -46,21 +41,24 @@ pub fn Decompress(comptime ReaderType: type) type {
4641
in_reader: ReaderType,
4742

4843
fn init(allocator: Allocator, source: ReaderType) !Self {
49-
const header = try source.readStruct(Header);
50-
51-
if (!std.mem.eql(u8, &header.magic, &.{ 0xFD, '7', 'z', 'X', 'Z', 0x00 }))
44+
const magic = try source.readBytesNoEof(6);
45+
if (!std.mem.eql(u8, &magic, &.{ 0xFD, '7', 'z', 'X', 'Z', 0x00 }))
5246
return error.BadHeader;
5347

54-
if (header.flags.reserved1 != 0 or header.flags.reserved2 != 0)
55-
return error.BadHeader;
48+
var check: Check = undefined;
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));
58-
if (hash != header.crc32)
55+
const hash_b = try source.readIntLittle(u32);
56+
if (hash_a != hash_b)
5957
return error.WrongChecksum;
6058

6159
return Self{
6260
.allocator = allocator,
63-
.block_decoder = try block.decoder(allocator, source, header.flags.check_kind),
61+
.block_decoder = try block.decoder(allocator, source, check),
6462
.in_reader = source,
6563
};
6664
}
@@ -114,22 +112,27 @@ pub fn Decompress(comptime ReaderType: type) type {
114112
break :blk counter.bytes_read;
115113
};
116114

117-
const footer = try self.in_reader.readStruct(Footer);
118-
const backward_size = (footer.backward_size + 1) * 4;
119-
if (backward_size != index_size)
120-
return error.CorruptInput;
115+
const hash_a = try self.in_reader.readIntLittle(u32);
121116

122-
if (footer.flags.reserved1 != 0 or footer.flags.reserved2 != 0)
123-
return error.CorruptInput;
117+
const hash_b = blk: {
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();
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)
131+
if (hash_a != hash_b)
130132
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' }))
133136
return error.CorruptInput;
134137

135138
return 0;

lib/std/compress/xz/block.zig

+1-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ pub fn Decoder(comptime ReaderType: type) type {
109109
has_unpacked_size: bool,
110110
};
111111

112-
const flags = try header_reader.readStruct(Flags);
112+
const flags = @bitCast(Flags, try header_reader.readByte());
113113
const filter_count = @as(u3, flags.last_filter_index) + 1;
114114
if (filter_count > 1)
115115
return error.Unsupported;

0 commit comments

Comments
 (0)