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
573573const match_table_size_max = 1 << types.compressed_block.table_accuracy_log_max.match;
574574const 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
576581const FrameError = error{
577582 DictionaryIdFlagUnsupported,
578583 ChecksumFailure,
......@@ -601,24 +606,20 @@ pub fn decodeZStandardFrame(
601606 if (dest.len < content_size) return error.ContentTooLarge;
602607
603608 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
606611 const written_count = try decodeFrameBlocks(
607612 dest,
608613 src[consumed_count..],
609614 &consumed_count,
610 if (should_compute_checksum) &hash_state else null,
615 if (hasher_opt) |*hasher| hasher else null,
611616 );
612617
613618 if (frame_header.descriptor.content_checksum_flag) {
614619 const checksum = readIntSlice(u32, src[consumed_count .. consumed_count + 4]);
615620 consumed_count += 4;
616 if (verify_checksum) {
617 const hash = hash_state.final();
618 const hash_low_bytes = hash & 0xFFFFFFFF;
619 if (checksum != hash_low_bytes) {
620 return error.ChecksumFailure;
621 }
621 if (hasher_opt) |*hasher| {
622 if (checksum != computeChecksum(hasher)) return error.ChecksumFailure;
622623 }
623624 }
624625 return ReadWriteCount{ .read_count = consumed_count, .write_count = written_count };
......@@ -649,7 +650,7 @@ pub fn decodeZStandardFrameAlloc(
649650 @intCast(usize, window_size_raw);
650651
651652 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
654655 const block_size_maximum = @min(1 << 17, window_size);
655656
......@@ -707,12 +708,20 @@ pub fn decodeZStandardFrameAlloc(
707708 const written_slice = ring_buffer.sliceLast(written_size);
708709 try result.appendSlice(written_slice.first);
709710 try result.appendSlice(written_slice.second);
710 if (hash) |*hash_state| {
711 hash_state.update(written_slice.first);
712 hash_state.update(written_slice.second);
711 if (hasher_opt) |*hasher| {
712 hasher.update(written_slice.first);
713 hasher.update(written_slice.second);
713714 }
714715 if (block_header.last_block) break;
715716 }
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 }
716725 return result.toOwnedSlice();
717726}
718727