authorgravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2023-02-02 16:54:31-08:00
committergravatar for fncontroloption@noreply.codeberg.orgFnControlOption <fncontroloption@noreply.codeberg.org> 2023-02-05 06:08:35-08:00
logd57813e3e94e77f54e989fa0814216389cf04a2b
tree9cced097b3807e83656b62c1282513f1dada2acc
parentbaa877fd129c7c6eb3c87c3e219bb4dede67b0a0

std.compress.xz: Avoid possible integer overflow in a few places


4 files changed, 23 insertions(+), 3 deletions(-)

lib/std/compress/lzma/decode/lzma2.zig+1-1
...@@ -155,7 +155,7 @@ pub const Lzma2Decoder = struct {...@@ -155,7 +155,7 @@ pub const Lzma2Decoder = struct {
155 accum: *LzAccumBuffer,155 accum: *LzAccumBuffer,
156 reset_dict: bool,156 reset_dict: bool,
157 ) !void {157 ) !void {
158 const unpacked_size = try reader.readIntBig(u16) + 1; // TODO: overflow158 const unpacked_size = @as(u17, try reader.readIntBig(u16)) + 1;
159159
160 if (reset_dict) {160 if (reset_dict) {
161 try accum.reset(writer);161 try accum.reset(writer);
lib/std/compress/xz.zig+1-1
...@@ -118,7 +118,7 @@ pub fn Decompress(comptime ReaderType: type) type {...@@ -118,7 +118,7 @@ pub fn Decompress(comptime ReaderType: type) type {
118 var hasher = std.compress.hashedReader(self.in_reader, Crc32.init());118 var hasher = std.compress.hashedReader(self.in_reader, Crc32.init());
119 const hashed_reader = hasher.reader();119 const hashed_reader = hasher.reader();
120120
121 const backward_size = (try hashed_reader.readIntLittle(u32) + 1) * 4;121 const backward_size = (@as(u64, try hashed_reader.readIntLittle(u32)) + 1) * 4;
122 if (backward_size != index_size)122 if (backward_size != index_size)
123 return error.CorruptInput;123 return error.CorruptInput;
124124
lib/std/compress/xz/block.zig+1-1
...@@ -97,7 +97,7 @@ pub fn Decoder(comptime ReaderType: type) type {...@@ -97,7 +97,7 @@ pub fn Decoder(comptime ReaderType: type) type {
97 var header_hasher = std.compress.hashedReader(block_reader, Crc32.init());97 var header_hasher = std.compress.hashedReader(block_reader, Crc32.init());
98 const header_reader = header_hasher.reader();98 const header_reader = header_hasher.reader();
9999
100 const header_size = try header_reader.readByte() * 4;100 const header_size = @as(u64, try header_reader.readByte()) * 4;
101 if (header_size == 0)101 if (header_size == 0)
102 return error.EndOfStreamWithNoError;102 return error.EndOfStreamWithNoError;
103103
lib/std/compress/xz/test.zig+20
...@@ -78,3 +78,23 @@ test "unsupported" {...@@ -78,3 +78,23 @@ test "unsupported" {
78 );78 );
79 }79 }
80}80}
81
82fn testDontPanic(data: []const u8) !void {
83 const buf = decompress(data) catch |err| switch (err) {
84 error.OutOfMemory => |e| return e,
85 else => return,
86 };
87 defer testing.allocator.free(buf);
88}
89
90test "size fields: integer overflow avoidance" {
91 // These cases were found via fuzz testing and each previously caused
92 // an integer overflow when decoding. We just want to ensure they no longer
93 // cause a panic
94 const header_size_overflow = "\xfd7zXZ\x00\x00\x01i\"\xde6z";
95 try testDontPanic(header_size_overflow);
96 const lzma2_chunk_size_overflow = "\xfd7zXZ\x00\x00\x01i\"\xde6\x02\x00!\x01\x08\x00\x00\x00\xd8\x0f#\x13\x01\xff\xff";
97 try testDontPanic(lzma2_chunk_size_overflow);
98 const backward_size_overflow = "\xfd7zXZ\x00\x00\x01i\"\xde6\x00\x00\x00\x00\x1c\xdfD!\x90B\x99\r\x01\x00\x00\xff\xff\x10\x00\x00\x00\x01DD\xff\xff\xff\x01";
99 try testDontPanic(backward_size_overflow);
100}