Commit 4c0913ff7c

Alex Rønne Petersen <alex@alexrp.com>
2025-03-31 17:50:32
Merge pull request #23417 from dweiller/zstd-fixes
Zstd fixes
1 parent e5ea175
Changed files (3)
lib
std
compress
lib/std/compress/zstandard/decode/block.zig
@@ -989,6 +989,7 @@ pub fn decodeLiteralsSection(
     const header = try decodeLiteralsHeader(source);
     switch (header.block_type) {
         .raw => {
+            if (buffer.len < header.regenerated_size) return error.LiteralsBufferTooSmall;
             try source.readNoEof(buffer[0..header.regenerated_size]);
             return LiteralsSection{
                 .header = header,
lib/std/compress/zstandard/decompress.zig
@@ -380,7 +380,7 @@ pub const FrameContext = struct {
     ///   - `error.WindowSizeUnknown` if the frame does not have a valid window
     ///     size
     ///   - `error.WindowTooLarge` if the window size is larger than
-    ///     `window_size_max`
+    ///     `window_size_max` or `std.math.intMax(usize)`
     ///   - `error.ContentSizeTooLarge` if the frame header indicates a content
     ///     size larger than `std.math.maxInt(usize)`
     pub fn init(
@@ -395,7 +395,7 @@ pub const FrameContext = struct {
         const window_size = if (window_size_raw > window_size_max)
             return error.WindowTooLarge
         else
-            @as(usize, @intCast(window_size_raw));
+            std.math.cast(usize, window_size_raw) orelse return error.WindowTooLarge;
 
         const should_compute_checksum =
             frame_header.descriptor.content_checksum_flag and verify_checksum;
lib/std/compress/zstandard.zig
@@ -289,3 +289,22 @@ test "zero sized block" {
     try expectEqualDecodedStreaming("", input_raw);
     try expectEqualDecodedStreaming("", input_rle);
 }
+
+test "declared raw literals size too large" {
+    const input_raw =
+        "\x28\xb5\x2f\xfd" ++ // zstandard frame magic number
+        "\x00\x00" ++ // frame header: everything unset, window descriptor zero
+        "\x95\x00\x00" ++ // block header with: last_block set, block_type compressed, block_size 18
+        "\xbc\xf3\xae" ++ // literals section header with: type raw, size_format 3, regenerated_size 716603
+        "\xa5\x9f\xe3"; // some bytes of literal content - the content is shorter than regenerated_size
+
+    // Note that the regenerated_size in the above input is larger than block maximum size, so the
+    // block can't be valid as it is a raw literals block.
+
+    var fbs = std.io.fixedBufferStream(input_raw);
+    var window: [1024]u8 = undefined;
+    var stream = decompressor(fbs.reader(), .{ .window_buffer = &window });
+
+    var buf: [1024]u8 = undefined;
+    try std.testing.expectError(error.MalformedBlock, stream.read(&buf));
+}