| ... | ... | @@ -573,6 +573,11 @@ const literal_table_size_max = 1 << types.compressed_block.table_accuracy_log_ma |
| 573 | 573 | const match_table_size_max = 1 << types.compressed_block.table_accuracy_log_max.match; |
| 574 | 574 | const offset_table_size_max = 1 << types.compressed_block.table_accuracy_log_max.match; |
| 575 | 575 | |
| 576 | pub fn computeChecksum(hasher: *std.hash.XxHash64) u32 { |
| 577 | const hash = hasher.final(); |
| 578 | return @intCast(u32, hash & 0xFFFFFFFF); |
| 579 | } |
| 580 | |
| 576 | 581 | const FrameError = error{ |
| 577 | 582 | DictionaryIdFlagUnsupported, |
| 578 | 583 | ChecksumFailure, |
| ... | ... | @@ -601,24 +606,20 @@ pub fn decodeZStandardFrame( |
| 601 | 606 | if (dest.len < content_size) return error.ContentTooLarge; |
| 602 | 607 | |
| 603 | 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; |
| 605 | 610 | |
| 606 | 611 | const written_count = try decodeFrameBlocks( |
| 607 | 612 | dest, |
| 608 | 613 | src[consumed_count..], |
| 609 | 614 | &consumed_count, |
| 610 | | if (should_compute_checksum) &hash_state else null, |
| 615 | if (hasher_opt) |*hasher| hasher else null, |
| 611 | 616 | ); |
| 612 | 617 | |
| 613 | 618 | if (frame_header.descriptor.content_checksum_flag) { |
| 614 | 619 | const checksum = readIntSlice(u32, src[consumed_count .. consumed_count + 4]); |
| 615 | 620 | 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; |
| 622 | 623 | } |
| 623 | 624 | } |
| 624 | 625 | return ReadWriteCount{ .read_count = consumed_count, .write_count = written_count }; |
| ... | ... | @@ -649,7 +650,7 @@ pub fn decodeZStandardFrameAlloc( |
| 649 | 650 | @intCast(usize, window_size_raw); |
| 650 | 651 | |
| 651 | 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; |
| 653 | 654 | |
| 654 | 655 | const block_size_maximum = @min(1 << 17, window_size); |
| 655 | 656 | |
| ... | ... | @@ -707,12 +708,20 @@ pub fn decodeZStandardFrameAlloc( |
| 707 | 708 | const written_slice = ring_buffer.sliceLast(written_size); |
| 708 | 709 | try result.appendSlice(written_slice.first); |
| 709 | 710 | 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); |
| 713 | 714 | } |
| 714 | 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 | 725 | return result.toOwnedSlice(); |
| 717 | 726 | } |
| 718 | 727 | |