From af7b27a21db7b5a38b212d6a94d14d7749cfed9c Mon Sep 17 00:00:00 2001 From: Chris Hennick <4961925+Pr0methean@users.noreply.github.com> Date: Fri, 14 Jun 2024 15:47:41 -0700 Subject: [PATCH] perf: Speed up CRC when encrypting small files --- src/write.rs | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/write.rs b/src/write.rs index 5dbeadd9..99739a03 100644 --- a/src/write.rs +++ b/src/write.rs @@ -1038,8 +1038,7 @@ impl ZipWriter { let file_end = writer.stream_position()?; debug_assert!(file_end >= self.stats.start); file.compressed_size = file_end - self.stats.start; - - file.crc32 = self.stats.hasher.clone().finalize(); + let mut crc = true; if let Some(aes_mode) = &mut file.aes_mode { // We prefer using AE-1 which provides an extra CRC check, but for small files we // switch to AE-2 to prevent being able to use the CRC value to to reconstruct the @@ -1047,13 +1046,17 @@ impl ZipWriter { // // C.f. https://www.winzip.com/en/support/aes-encryption/#crc-faq aes_mode.1 = if self.stats.bytes_written < 20 { - file.crc32 = 0; + crc = false; AesVendorVersion::Ae2 } else { AesVendorVersion::Ae1 - } + }; } - + file.crc32 = if (crc) { + self.stats.hasher.clone().finalize() + } else { + 0 + }; update_aes_extra_data(writer, file)?; update_local_file_header(writer, file)?; writer.seek(SeekFrom::Start(file_end))?; @@ -2722,4 +2725,17 @@ mod test { let _ = writer.finish_into_readable()?; Ok(()) } + + #[test] + fn test_fuzz_crash_2024_06_14a() -> ZipResult<()> { + let mut writer = ZipWriter::new(Cursor::new(Vec::new())); + writer.set_flush_on_finish_file(false); + let options = FileOptions { compression_method: Stored, compression_level: None, last_modified_time: DateTime::from_date_and_time(2083, 5, 30, 21, 45, 35)?, permissions: None, large_file: false, encrypt_with: None, extended_options: ExtendedFileOptions {extra_data: vec![].into(), central_extra_data: vec![].into()}, alignment: 2565, ..Default::default() }; + writer.add_symlink_from_path("", "", options)?; + writer.abort_file()?; + let options = FileOptions { compression_method: Stored, compression_level: None, last_modified_time: DateTime::default(), permissions: None, large_file: false, encrypt_with: None, extended_options: ExtendedFileOptions {extra_data: vec![].into(), central_extra_data: vec![].into()}, alignment: 0, ..Default::default() }; + writer.start_file_from_path("", options)?; + let _ = writer.finish_into_readable()?; + Ok(()) + } }