From 00c1199dbe9f10d83d0fa8b6b07b86d75d897bad Mon Sep 17 00:00:00 2001 From: Rouven Spreckels Date: Fri, 25 Mar 2022 15:57:00 +0100 Subject: [PATCH] Use `ZIP64_BYTES_THR` and `ZIP64_ENTRY_THR`. --- src/read.rs | 6 +++--- src/spec.rs | 3 +++ src/write.rs | 57 ++++++++++++++++------------------------------------ 3 files changed, 23 insertions(+), 43 deletions(-) diff --git a/src/read.rs b/src/read.rs index 12791238..7bdb9fc6 100644 --- a/src/read.rs +++ b/src/read.rs @@ -727,17 +727,17 @@ fn parse_extra_field(file: &mut ZipFileData) -> ZipResult<()> { match kind { // Zip64 extended information extra field 0x0001 => { - if file.uncompressed_size == 0xFFFFFFFF { + if file.uncompressed_size == spec::ZIP64_BYTES_THR { file.large_file = true; file.uncompressed_size = reader.read_u64::()?; len_left -= 8; } - if file.compressed_size == 0xFFFFFFFF { + if file.compressed_size == spec::ZIP64_BYTES_THR { file.large_file = true; file.compressed_size = reader.read_u64::()?; len_left -= 8; } - if file.header_start == 0xFFFFFFFF { + if file.header_start == spec::ZIP64_BYTES_THR { file.header_start = reader.read_u64::()?; len_left -= 8; } diff --git a/src/spec.rs b/src/spec.rs index 4ab3656d..3ffcf732 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -9,6 +9,9 @@ const CENTRAL_DIRECTORY_END_SIGNATURE: u32 = 0x06054b50; pub const ZIP64_CENTRAL_DIRECTORY_END_SIGNATURE: u32 = 0x06064b50; const ZIP64_CENTRAL_DIRECTORY_END_LOCATOR_SIGNATURE: u32 = 0x07064b50; +pub const ZIP64_BYTES_THR: u64 = u32::MAX as u64; +pub const ZIP64_ENTRY_THR: usize = u16::MAX as usize; + pub struct CentralDirectoryEnd { pub disk_number: u16, pub disk_with_central_directory: u16, diff --git a/src/write.rs b/src/write.rs index a9616b04..3d0e0170 100644 --- a/src/write.rs +++ b/src/write.rs @@ -216,7 +216,7 @@ impl Write for ZipWriter { let write_result = w.write(buf); if let Ok(count) = write_result { self.stats.update(&buf[0..count]); - if self.stats.bytes_written > 0xFFFFFFFF + if self.stats.bytes_written > spec::ZIP64_BYTES_THR && !self.files.last_mut().unwrap().large_file { let _inner = mem::replace(&mut self.inner, GenericZipWriter::Closed); @@ -647,7 +647,7 @@ impl ZipWriter { S: Into, { let mut options = FileOptions::default() - .large_file(file.compressed_size().max(file.size()) > 0xFFFFFFFF) + .large_file(file.compressed_size().max(file.size()) > spec::ZIP64_BYTES_THR) .last_modified_time(file.last_modified()) .compression_method(file.compression()); if let Some(perms) = file.unix_mode() { @@ -760,7 +760,8 @@ impl ZipWriter { } let central_size = writer.seek(io::SeekFrom::Current(0))? - central_start; - if self.files.len() > 0xFFFF || central_size > 0xFFFFFFFF || central_start > 0xFFFFFFFF + if self.files.len() > spec::ZIP64_ENTRY_THR + || central_size.max(central_start) > spec::ZIP64_BYTES_THR { let zip64_footer = spec::Zip64CentralDirectoryEnd { version_made_by: DEFAULT_VERSION as u16, @@ -784,27 +785,15 @@ impl ZipWriter { zip64_footer.write(writer)?; } - let number_of_files = if self.files.len() > 0xFFFF { - 0xFFFF - } else { - self.files.len() as u16 - }; + let number_of_files = self.files.len().min(spec::ZIP64_ENTRY_THR) as u16; let footer = spec::CentralDirectoryEnd { disk_number: 0, disk_with_central_directory: 0, zip_file_comment: self.comment.clone(), number_of_files_on_this_disk: number_of_files, number_of_files, - central_directory_size: if central_size > 0xFFFFFFFF { - 0xFFFFFFFF - } else { - central_size as u32 - }, - central_directory_offset: if central_start > 0xFFFFFFFF { - 0xFFFFFFFF - } else { - central_start as u32 - }, + central_directory_size: central_size.min(spec::ZIP64_BYTES_THR) as u32, + central_directory_offset: central_start.min(spec::ZIP64_BYTES_THR) as u32, }; footer.write(writer)?; @@ -1030,8 +1019,8 @@ fn write_local_file_header(writer: &mut T, file: &ZipFileData) -> ZipR writer.write_u32::(file.crc32)?; // compressed size and uncompressed size if file.large_file { - writer.write_u32::(0xFFFFFFFF)?; - writer.write_u32::(0xFFFFFFFF)?; + writer.write_u32::(spec::ZIP64_BYTES_THR as u32)?; + writer.write_u32::(spec::ZIP64_BYTES_THR as u32)?; } else { writer.write_u32::(file.compressed_size as u32)?; writer.write_u32::(file.uncompressed_size as u32)?; @@ -1062,7 +1051,7 @@ fn update_local_file_header( update_local_zip64_extra_field(writer, file)?; } else { // check compressed size as well as it can also be slightly larger than uncompressed size - if file.compressed_size > 0xFFFFFFFF { + if file.compressed_size > spec::ZIP64_BYTES_THR { return Err(ZipError::Io(io::Error::new( io::ErrorKind::Other, "Large file option has not been set", @@ -1104,17 +1093,9 @@ fn write_central_directory_header(writer: &mut T, file: &ZipFileData) // crc-32 writer.write_u32::(file.crc32)?; // compressed size - writer.write_u32::(if file.compressed_size > 0xFFFFFFFF { - 0xFFFFFFFF - } else { - file.compressed_size as u32 - })?; + writer.write_u32::(file.compressed_size.min(spec::ZIP64_BYTES_THR) as u32)?; // uncompressed size - writer.write_u32::(if file.uncompressed_size > 0xFFFFFFFF { - 0xFFFFFFFF - } else { - file.uncompressed_size as u32 - })?; + writer.write_u32::(file.uncompressed_size.min(spec::ZIP64_BYTES_THR) as u32)?; // file name length writer.write_u16::(file.file_name.as_bytes().len() as u16)?; // extra field length @@ -1128,11 +1109,7 @@ fn write_central_directory_header(writer: &mut T, file: &ZipFileData) // external file attributes writer.write_u32::(file.external_attributes)?; // relative offset of local header - writer.write_u32::(if file.header_start > 0xFFFFFFFF { - 0xFFFFFFFF - } else { - file.header_start as u32 - })?; + writer.write_u32::(file.header_start.min(spec::ZIP64_BYTES_THR) as u32)?; // file name writer.write_all(file.file_name.as_bytes())?; // zip64 extra field @@ -1148,7 +1125,7 @@ fn write_central_directory_header(writer: &mut T, file: &ZipFileData) fn validate_extra_data(file: &ZipFileData) -> ZipResult<()> { let mut data = file.extra_field.as_slice(); - if data.len() > 0xFFFF { + if data.len() > spec::ZIP64_ENTRY_THR { return Err(ZipError::Io(io::Error::new( io::ErrorKind::InvalidData, "Extra data exceeds extra field", @@ -1231,9 +1208,9 @@ fn write_central_zip64_extra_field(writer: &mut T, file: &ZipFileData) // only appear if the corresponding Local or Central // directory record field is set to 0xFFFF or 0xFFFFFFFF. let mut size = 0; - let uncompressed_size = file.uncompressed_size > 0xFFFFFFFF; - let compressed_size = file.compressed_size > 0xFFFFFFFF; - let header_start = file.header_start > 0xFFFFFFFF; + let uncompressed_size = file.uncompressed_size > spec::ZIP64_BYTES_THR; + let compressed_size = file.compressed_size > spec::ZIP64_BYTES_THR; + let header_start = file.header_start > spec::ZIP64_BYTES_THR; if uncompressed_size { size += 8; }