authorgravatar for 4678790+dweiller@users.noreply.github.comDominic <4678790+dweiller@users.noreply.github.com> 2023-02-02 18:01:03+11:00
committergravatar for 4678790+dweiller@users.noreply.github.comDominic <4678790+dweiller@users.noreply.github.com> 2023-02-20 09:09:06+11:00
log6e3e72884bdc1a2f9f3ae372716b50803565e696
tree46cb12b36bbf3f64f93d874c49e8cd9adc5b2848
parenta180fcc93d3eff8add7b0344ddc77241dcf78f1e

std.compress.zstandard: fix crashes


1 files changed, 12 insertions(+), 6 deletions(-)

lib/std/compress/zstandard/decompress.zig+12-6
...@@ -695,11 +695,11 @@ pub fn decodeZStandardFrameAlloc(...@@ -695,11 +695,11 @@ pub fn decodeZStandardFrameAlloc(
695 var match_fse_data: [types.compressed_block.table_size_max.match]Table.Fse = undefined;695 var match_fse_data: [types.compressed_block.table_size_max.match]Table.Fse = undefined;
696 var offset_fse_data: [types.compressed_block.table_size_max.offset]Table.Fse = undefined;696 var offset_fse_data: [types.compressed_block.table_size_max.offset]Table.Fse = undefined;
697697
698 var block_header = decodeBlockHeader(src[consumed_count..][0..3]);698 var block_header = try decodeBlockHeaderSlice(src[consumed_count..]);
699 consumed_count += 3;699 consumed_count += 3;
700 var decode_state = DecodeState.init(&literal_fse_data, &match_fse_data, &offset_fse_data);700 var decode_state = DecodeState.init(&literal_fse_data, &match_fse_data, &offset_fse_data);
701 while (true) : ({701 while (true) : ({
702 block_header = decodeBlockHeader(src[consumed_count..][0..3]);702 block_header = try decodeBlockHeaderSlice(src[consumed_count..]);
703 consumed_count += 3;703 consumed_count += 3;
704 }) {704 }) {
705 if (block_header.block_size > frame_context.block_size_max) return error.BlockSizeOverMaximum;705 if (block_header.block_size > frame_context.block_size_max) return error.BlockSizeOverMaximum;
...@@ -737,6 +737,7 @@ const DecodeBlockError = error{...@@ -737,6 +737,7 @@ const DecodeBlockError = error{
737 ReservedBlock,737 ReservedBlock,
738 MalformedRleBlock,738 MalformedRleBlock,
739 MalformedCompressedBlock,739 MalformedCompressedBlock,
740 EndOfStream,
740};741};
741742
742/// Convenience wrapper for decoding all blocks in a frame; see `decodeBlock()`.743/// Convenience wrapper for decoding all blocks in a frame; see `decodeBlock()`.
...@@ -751,13 +752,13 @@ pub fn decodeFrameBlocks(...@@ -751,13 +752,13 @@ pub fn decodeFrameBlocks(
751 var match_fse_data: [types.compressed_block.table_size_max.match]Table.Fse = undefined;752 var match_fse_data: [types.compressed_block.table_size_max.match]Table.Fse = undefined;
752 var offset_fse_data: [types.compressed_block.table_size_max.offset]Table.Fse = undefined;753 var offset_fse_data: [types.compressed_block.table_size_max.offset]Table.Fse = undefined;
753754
754 var block_header = decodeBlockHeader(src[0..3]);755 var block_header = try decodeBlockHeaderSlice(src);
755 var bytes_read: usize = 3;756 var bytes_read: usize = 3;
756 defer consumed_count.* += bytes_read;757 defer consumed_count.* += bytes_read;
757 var decode_state = DecodeState.init(&literal_fse_data, &match_fse_data, &offset_fse_data);758 var decode_state = DecodeState.init(&literal_fse_data, &match_fse_data, &offset_fse_data);
758 var written_count: usize = 0;759 var written_count: usize = 0;
759 while (true) : ({760 while (true) : ({
760 block_header = decodeBlockHeader(src[bytes_read..][0..3]);761 block_header = try decodeBlockHeaderSlice(src[bytes_read..]);
761 bytes_read += 3;762 bytes_read += 3;
762 }) {763 }) {
763 const written_size = try decodeBlock(764 const written_size = try decodeBlock(
...@@ -847,6 +848,7 @@ pub fn decodeBlock(...@@ -847,6 +848,7 @@ pub fn decodeBlock(
847848
848 bytes_read += bit_stream_bytes.len;849 bytes_read += bit_stream_bytes.len;
849 }850 }
851 if (bytes_read != block_size) return error.MalformedCompressedBlock;
850852
851 if (decode_state.literal_written_count < literals.header.regenerated_size) {853 if (decode_state.literal_written_count < literals.header.regenerated_size) {
852 const len = literals.header.regenerated_size - decode_state.literal_written_count;854 const len = literals.header.regenerated_size - decode_state.literal_written_count;
...@@ -855,7 +857,6 @@ pub fn decodeBlock(...@@ -855,7 +857,6 @@ pub fn decodeBlock(
855 bytes_written += len;857 bytes_written += len;
856 }858 }
857859
858 assert(bytes_read == block_header.block_size);
859 consumed_count.* += bytes_read;860 consumed_count.* += bytes_read;
860 return bytes_written;861 return bytes_written;
861 },862 },
...@@ -931,6 +932,7 @@ pub fn decodeBlockRingBuffer(...@@ -931,6 +932,7 @@ pub fn decodeBlockRingBuffer(
931932
932 bytes_read += bit_stream_bytes.len;933 bytes_read += bit_stream_bytes.len;
933 }934 }
935 if (bytes_read != block_size) return error.MalformedCompressedBlock;
934936
935 if (decode_state.literal_written_count < literals.header.regenerated_size) {937 if (decode_state.literal_written_count < literals.header.regenerated_size) {
936 const len = literals.header.regenerated_size - decode_state.literal_written_count;938 const len = literals.header.regenerated_size - decode_state.literal_written_count;
...@@ -939,7 +941,6 @@ pub fn decodeBlockRingBuffer(...@@ -939,7 +941,6 @@ pub fn decodeBlockRingBuffer(
939 bytes_written += len;941 bytes_written += len;
940 }942 }
941943
942 assert(bytes_read == block_header.block_size);
943 consumed_count.* += bytes_read;944 consumed_count.* += bytes_read;
944 if (bytes_written > block_size_max) return error.BlockSizeOverMaximum;945 if (bytes_written > block_size_max) return error.BlockSizeOverMaximum;
945 return bytes_written;946 return bytes_written;
...@@ -1101,6 +1102,11 @@ pub fn decodeBlockHeader(src: *const [3]u8) frame.ZStandard.Block.Header {...@@ -1101,6 +1102,11 @@ pub fn decodeBlockHeader(src: *const [3]u8) frame.ZStandard.Block.Header {
1101 };1102 };
1102}1103}
11031104
1105pub fn decodeBlockHeaderSlice(src: []const u8) error{EndOfStream}!frame.ZStandard.Block.Header {
1106 if (src.len < 3) return error.EndOfStream;
1107 return decodeBlockHeader(src[0..3]);
1108}
1109
1104/// Decode a `LiteralsSection` from `src`, incrementing `consumed_count` by the1110/// Decode a `LiteralsSection` from `src`, incrementing `consumed_count` by the
1105/// number of bytes the section uses.1111/// number of bytes the section uses.
1106///1112///