authorgravatar for 4678790+dweiller@users.noreply.github.comDominic <4678790+dweiller@users.noreply.github.com> 2023-01-28 22:02:08+11:00
committergravatar for 4678790+dweiller@users.noreply.github.comDominic <4678790+dweiller@users.noreply.github.com> 2023-02-20 09:09:06+11:00
loge92575d3d47b2701d0b93aa0f044caade57b71c8
tree1e3308da0bbb3df4d28c898d8cf0546974270348
parent3bfba365483ccf30b197195cce8d5656f2c73736

std.compress.zstandard: verify checksum in decodeFrameAlloc()


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

lib/std/compress/zstandard/decompress.zig+21-12
...@@ -573,6 +573,11 @@ const literal_table_size_max = 1 << types.compressed_block.table_accuracy_log_ma...@@ -573,6 +573,11 @@ const literal_table_size_max = 1 << types.compressed_block.table_accuracy_log_ma
573const match_table_size_max = 1 << types.compressed_block.table_accuracy_log_max.match;573const match_table_size_max = 1 << types.compressed_block.table_accuracy_log_max.match;
574const offset_table_size_max = 1 << types.compressed_block.table_accuracy_log_max.match;574const offset_table_size_max = 1 << types.compressed_block.table_accuracy_log_max.match;
575575
576pub fn computeChecksum(hasher: *std.hash.XxHash64) u32 {
577 const hash = hasher.final();
578 return @intCast(u32, hash & 0xFFFFFFFF);
579}
580
576const FrameError = error{581const FrameError = error{
577 DictionaryIdFlagUnsupported,582 DictionaryIdFlagUnsupported,
578 ChecksumFailure,583 ChecksumFailure,
...@@ -601,24 +606,20 @@ pub fn decodeZStandardFrame(...@@ -601,24 +606,20 @@ pub fn decodeZStandardFrame(
601 if (dest.len < content_size) return error.ContentTooLarge;606 if (dest.len < content_size) return error.ContentTooLarge;
602607
603 const should_compute_checksum = frame_header.descriptor.content_checksum_flag and verify_checksum;608 const should_compute_checksum = frame_header.descriptor.content_checksum_flag and verify_checksum;
604 var hash_state = if (should_compute_checksum) std.hash.XxHash64.init(0) else undefined;609 var hasher_opt = if (should_compute_checksum) std.hash.XxHash64.init(0) else null;
605610
606 const written_count = try decodeFrameBlocks(611 const written_count = try decodeFrameBlocks(
607 dest,612 dest,
608 src[consumed_count..],613 src[consumed_count..],
609 &consumed_count,614 &consumed_count,
610 if (should_compute_checksum) &hash_state else null,615 if (hasher_opt) |*hasher| hasher else null,
611 );616 );
612617
613 if (frame_header.descriptor.content_checksum_flag) {618 if (frame_header.descriptor.content_checksum_flag) {
614 const checksum = readIntSlice(u32, src[consumed_count .. consumed_count + 4]);619 const checksum = readIntSlice(u32, src[consumed_count .. consumed_count + 4]);
615 consumed_count += 4;620 consumed_count += 4;
616 if (verify_checksum) {621 if (hasher_opt) |*hasher| {
617 const hash = hash_state.final();622 if (checksum != computeChecksum(hasher)) return error.ChecksumFailure;
618 const hash_low_bytes = hash & 0xFFFFFFFF;
619 if (checksum != hash_low_bytes) {
620 return error.ChecksumFailure;
621 }
622 }623 }
623 }624 }
624 return ReadWriteCount{ .read_count = consumed_count, .write_count = written_count };625 return ReadWriteCount{ .read_count = consumed_count, .write_count = written_count };
...@@ -649,7 +650,7 @@ pub fn decodeZStandardFrameAlloc(...@@ -649,7 +650,7 @@ pub fn decodeZStandardFrameAlloc(
649 @intCast(usize, window_size_raw);650 @intCast(usize, window_size_raw);
650651
651 const should_compute_checksum = frame_header.descriptor.content_checksum_flag and verify_checksum;652 const should_compute_checksum = frame_header.descriptor.content_checksum_flag and verify_checksum;
652 var hash = if (should_compute_checksum) std.hash.XxHash64.init(0) else null;653 var hasher_opt = if (should_compute_checksum) std.hash.XxHash64.init(0) else null;
653654
654 const block_size_maximum = @min(1 << 17, window_size);655 const block_size_maximum = @min(1 << 17, window_size);
655656
...@@ -707,12 +708,20 @@ pub fn decodeZStandardFrameAlloc(...@@ -707,12 +708,20 @@ pub fn decodeZStandardFrameAlloc(
707 const written_slice = ring_buffer.sliceLast(written_size);708 const written_slice = ring_buffer.sliceLast(written_size);
708 try result.appendSlice(written_slice.first);709 try result.appendSlice(written_slice.first);
709 try result.appendSlice(written_slice.second);710 try result.appendSlice(written_slice.second);
710 if (hash) |*hash_state| {711 if (hasher_opt) |*hasher| {
711 hash_state.update(written_slice.first);712 hasher.update(written_slice.first);
712 hash_state.update(written_slice.second);713 hasher.update(written_slice.second);
713 }714 }
714 if (block_header.last_block) break;715 if (block_header.last_block) break;
715 }716 }
717
718 if (frame_header.descriptor.content_checksum_flag) {
719 const checksum = readIntSlice(u32, src[consumed_count .. consumed_count + 4]);
720 consumed_count += 4;
721 if (hasher_opt) |*hasher| {
722 if (checksum != computeChecksum(hasher)) return error.ChecksumFailure;
723 }
724 }
716 return result.toOwnedSlice();725 return result.toOwnedSlice();
717}726}
718727