From e334f15f12fc070b3528433e500a77966c9eafdd Mon Sep 17 00:00:00 2001 From: Chris Hennick <4961925+Pr0methean@users.noreply.github.com> Date: Thu, 9 May 2024 18:00:40 -0700 Subject: [PATCH] Fix bad merge: revert deletion of zip64 extra field --- src/write.rs | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/src/write.rs b/src/write.rs index 7bbfa5a6..55d96578 100644 --- a/src/write.rs +++ b/src/write.rs @@ -860,6 +860,71 @@ impl ZipWriter { if file.large_file { write_local_zip64_extra_field(writer, file)?; } + if let Some(extra_field) = &file.extra_field { + file.extra_data_start = Some(writer.stream_position()?); + writer.write_all(extra_field)?; + } + let mut header_end = writer.stream_position()?; + if options.alignment > 1 { + let align = options.alignment as u64; + let unaligned_header_bytes = header_end % align; + if unaligned_header_bytes != 0 { + let pad_length = (align - unaligned_header_bytes) as usize; + let Some(new_extra_field_length) = + (pad_length as u16).checked_add(extra_field_length) + else { + let _ = self.abort_file(); + return Err(InvalidArchive( + "Extra data field would be larger than allowed after aligning", + )); + }; + if pad_length >= 4 { + // Add an extra field to the extra_data + let pad_body = vec![0; pad_length - 4]; + writer.write_all(b"za").map_err(ZipError::from)?; // 0x617a + writer + .write_u16_le(pad_body.len() as u16) + .map_err(ZipError::from)?; + writer.write_all(&pad_body).map_err(ZipError::from)?; + } else { + // extra_data padding is too small for an extra field header, so pad with + // zeroes + let pad = vec![0; pad_length]; + writer.write_all(&pad).map_err(ZipError::from)?; + } + header_end = writer.stream_position()?; + + // Update extra field length in local file header. + writer.seek(SeekFrom::Start(file.header_start + 28))?; + writer.write_u16_le(new_extra_field_length)?; + writer.seek(SeekFrom::Start(header_end))?; + debug_assert_eq!(header_end % align, 0); + } + } + match options.encrypt_with { + #[cfg(feature = "aes-crypto")] + Some(EncryptWith::Aes { mode, password }) => { + let aeswriter = AesWriter::new( + mem::replace(&mut self.inner, GenericZipWriter::Closed).unwrap(), + mode, + password.as_bytes(), + )?; + self.inner = GenericZipWriter::Storer(MaybeEncrypted::Aes(aeswriter)); + } + Some(EncryptWith::ZipCrypto(keys, ..)) => { + let mut zipwriter = crate::zipcrypto::ZipCryptoWriter { + writer: mem::replace(&mut self.inner, Closed).unwrap(), + buffer: vec![], + keys, + }; + let crypto_header = [0u8; 12]; + + zipwriter.write_all(&crypto_header)?; + header_end = zipwriter.writer.stream_position()?; + self.inner = Storer(MaybeEncrypted::ZipCrypto(zipwriter)); + } + None => {} + } self.stats.start = header_end; debug_assert!(file.data_start.get().is_none()); file.data_start.get_or_init(|| header_end);