Commit 594158a692

Veikka Tuominen <git@vexu.eu>
2022-12-04 13:32:25
Merge pull request #13142 from mllken/gzip-safety
gzip: add missing header fields and bounds for header parsing
1 parent af958e9
Changed files (1)
lib
std
compress
lib/std/compress/gzip.zig
@@ -15,6 +15,8 @@ const FEXTRA = 1 << 2;
 const FNAME = 1 << 3;
 const FCOMMENT = 1 << 4;
 
+const max_string_len = 1024;
+
 pub fn GzipStream(comptime ReaderType: type) type {
     return struct {
         const Self = @This();
@@ -31,9 +33,11 @@ pub fn GzipStream(comptime ReaderType: type) type {
         read_amt: usize,
 
         info: struct {
+            extra: ?[]const u8,
             filename: ?[]const u8,
             comment: ?[]const u8,
             modification_time: u32,
+            operating_system: u8,
         },
 
         fn init(allocator: mem.Allocator, source: ReaderType) !Self {
@@ -57,33 +61,27 @@ pub fn GzipStream(comptime ReaderType: type) type {
             // Operating system where the compression took place
             const OS = header[9];
             _ = XFL;
-            _ = OS;
 
-            if (FLG & FEXTRA != 0) {
-                // Skip the extra data, we could read and expose it to the user
-                // if somebody needs it.
+            const extra = if (FLG & FEXTRA != 0) blk: {
                 const len = try source.readIntLittle(u16);
-                try source.skipBytes(len, .{});
-            }
-
-            var filename: ?[]const u8 = null;
-            if (FLG & FNAME != 0) {
-                filename = try source.readUntilDelimiterAlloc(
-                    allocator,
-                    0,
-                    std.math.maxInt(usize),
-                );
-            }
+                const tmp_buf = try allocator.alloc(u8, len);
+                errdefer allocator.free(tmp_buf);
+
+                try source.readNoEof(tmp_buf);
+                break :blk tmp_buf;
+            } else null;
+            errdefer if (extra) |p| allocator.free(p);
+
+            const filename = if (FLG & FNAME != 0)
+                try source.readUntilDelimiterAlloc(allocator, 0, max_string_len)
+            else
+                null;
             errdefer if (filename) |p| allocator.free(p);
 
-            var comment: ?[]const u8 = null;
-            if (FLG & FCOMMENT != 0) {
-                comment = try source.readUntilDelimiterAlloc(
-                    allocator,
-                    0,
-                    std.math.maxInt(usize),
-                );
-            }
+            const comment = if (FLG & FCOMMENT != 0)
+                try source.readUntilDelimiterAlloc(allocator, 0, max_string_len)
+            else
+                null;
             errdefer if (comment) |p| allocator.free(p);
 
             if (FLG & FHCRC != 0) {
@@ -100,7 +98,9 @@ pub fn GzipStream(comptime ReaderType: type) type {
                 .info = .{
                     .filename = filename,
                     .comment = comment,
+                    .extra = extra,
                     .modification_time = MTIME,
+                    .operating_system = OS,
                 },
                 .read_amt = 0,
             };
@@ -108,6 +108,8 @@ pub fn GzipStream(comptime ReaderType: type) type {
 
         pub fn deinit(self: *Self) void {
             self.inflater.deinit();
+            if (self.info.extra) |extra|
+                self.allocator.free(extra);
             if (self.info.filename) |filename|
                 self.allocator.free(filename);
             if (self.info.comment) |comment|