authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-03-31 17:50:32+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-03-31 17:52:23+02:00
log4c0913ff7c1e6839f2a39f9932482664db5bc21d
treefc04f9b0fa952663a225154d1596a2da6deca2eb
parente5ea175ffb1a8339dd9169deebfacf4b943ddf72
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

Merge pull request #23417 from dweiller/zstd-fixes

Zstd fixes

3 files changed, 22 insertions(+), 2 deletions(-)

lib/std/compress/zstandard.zig+19
...@@ -289,3 +289,22 @@ test "zero sized block" {...@@ -289,3 +289,22 @@ test "zero sized block" {
289 try expectEqualDecodedStreaming("", input_raw);289 try expectEqualDecodedStreaming("", input_raw);
290 try expectEqualDecodedStreaming("", input_rle);290 try expectEqualDecodedStreaming("", input_rle);
291}291}
292
293test "declared raw literals size too large" {
294 const input_raw =
295 "\x28\xb5\x2f\xfd" ++ // zstandard frame magic number
296 "\x00\x00" ++ // frame header: everything unset, window descriptor zero
297 "\x95\x00\x00" ++ // block header with: last_block set, block_type compressed, block_size 18
298 "\xbc\xf3\xae" ++ // literals section header with: type raw, size_format 3, regenerated_size 716603
299 "\xa5\x9f\xe3"; // some bytes of literal content - the content is shorter than regenerated_size
300
301 // Note that the regenerated_size in the above input is larger than block maximum size, so the
302 // block can't be valid as it is a raw literals block.
303
304 var fbs = std.io.fixedBufferStream(input_raw);
305 var window: [1024]u8 = undefined;
306 var stream = decompressor(fbs.reader(), .{ .window_buffer = &window });
307
308 var buf: [1024]u8 = undefined;
309 try std.testing.expectError(error.MalformedBlock, stream.read(&buf));
310}
lib/std/compress/zstandard/decode/block.zig+1
...@@ -989,6 +989,7 @@ pub fn decodeLiteralsSection(...@@ -989,6 +989,7 @@ pub fn decodeLiteralsSection(
989 const header = try decodeLiteralsHeader(source);989 const header = try decodeLiteralsHeader(source);
990 switch (header.block_type) {990 switch (header.block_type) {
991 .raw => {991 .raw => {
992 if (buffer.len < header.regenerated_size) return error.LiteralsBufferTooSmall;
992 try source.readNoEof(buffer[0..header.regenerated_size]);993 try source.readNoEof(buffer[0..header.regenerated_size]);
993 return LiteralsSection{994 return LiteralsSection{
994 .header = header,995 .header = header,
lib/std/compress/zstandard/decompress.zig+2-2
...@@ -380,7 +380,7 @@ pub const FrameContext = struct {...@@ -380,7 +380,7 @@ pub const FrameContext = struct {
380 /// - `error.WindowSizeUnknown` if the frame does not have a valid window380 /// - `error.WindowSizeUnknown` if the frame does not have a valid window
381 /// size381 /// size
382 /// - `error.WindowTooLarge` if the window size is larger than382 /// - `error.WindowTooLarge` if the window size is larger than
383 /// `window_size_max`383 /// `window_size_max` or `std.math.intMax(usize)`
384 /// - `error.ContentSizeTooLarge` if the frame header indicates a content384 /// - `error.ContentSizeTooLarge` if the frame header indicates a content
385 /// size larger than `std.math.maxInt(usize)`385 /// size larger than `std.math.maxInt(usize)`
386 pub fn init(386 pub fn init(
...@@ -395,7 +395,7 @@ pub const FrameContext = struct {...@@ -395,7 +395,7 @@ pub const FrameContext = struct {
395 const window_size = if (window_size_raw > window_size_max)395 const window_size = if (window_size_raw > window_size_max)
396 return error.WindowTooLarge396 return error.WindowTooLarge
397 else397 else
398 @as(usize, @intCast(window_size_raw));398 std.math.cast(usize, window_size_raw) orelse return error.WindowTooLarge;
399399
400 const should_compute_checksum =400 const should_compute_checksum =
401 frame_header.descriptor.content_checksum_flag and verify_checksum;401 frame_header.descriptor.content_checksum_flag and verify_checksum;