Test allowing ZIP64 magic with the sanity checks

This commit is contained in:
Chris Hennick 2023-05-12 08:36:33 -07:00
parent 70db61c26e
commit 546693a6c7
No known key found for this signature in database
GPG key ID: 25653935CC8B6C74
5 changed files with 21 additions and 55 deletions

View file

@ -118,10 +118,3 @@
- Added experimental [`zip_next::unstable::write::FileOptions::with_deprecated_encryption`] API to enable encrypting
files with PKWARE encryption.
## [0.7.5]
### Fixed
- Two magic strings are no longer allowed in filenames, because they can make files impossible to read correctly.
- Archives containing these magic files can still be opened in many cases.

View file

@ -24,7 +24,6 @@ pbkdf2 = {version = "0.12.1", optional = true }
sha1 = {version = "0.10.5", optional = true }
time = { version = "0.3.21", optional = true, default-features = false, features = ["std"] }
zstd = { version = "0.12.3", optional = true }
visibility = "0.0.1"
[target.'cfg(any(all(target_arch = "arm", target_pointer_width = "32"), target_arch = "mips", target_arch = "powerpc"))'.dependencies]
crossbeam-utils = "0.8.15"

View file

@ -51,9 +51,6 @@ impl FileOperation {
fn do_operation<T>(writer: &mut RefCell<zip_next::ZipWriter<T>>,
operation: &FileOperation) -> Result<(), Box<dyn std::error::Error>>
where T: Read + Write + Seek {
if zip_next::write::validate_name(&operation.get_name()).is_err() {
return Ok(());
}
match operation {
FileOperation::Write {file, mut options, ..} => {
if file.contents.iter().map(Vec::len).sum::<usize>() >= u32::MAX as usize {

View file

@ -357,10 +357,9 @@ impl<R: Read + Seek> ZipArchive<R> {
));
}
let supported = if footer64.disk_number != footer64.disk_with_central_directory {
unsupported_zip_error("Support for multi-disk files is not implemented")
} else if !footer.record_too_small()
&& footer.disk_number as u32 != locator64.disk_with_central_directory
let supported = if (footer64.disk_number != footer64.disk_with_central_directory)
|| (!footer.record_too_small()
&& footer.disk_number as u32 != locator64.disk_with_central_directory)
{
unsupported_zip_error("Support for multi-disk files is not implemented")
} else {
@ -371,7 +370,7 @@ impl<R: Read + Seek> ZipArchive<R> {
archive_offset,
directory_start,
footer64.number_of_files as usize,
supported
supported,
))
}
@ -383,37 +382,39 @@ impl<R: Read + Seek> ZipArchive<R> {
cde_start_pos: u64,
) -> ZipResult<(u64, u64, usize)> {
// Check if file has a zip64 footer
let (archive_offset_64, directory_start_64, number_of_files_64,
supported_64) =
let (archive_offset_64, directory_start_64, number_of_files_64, supported_64) =
match Self::get_directory_counts_zip64(reader, footer, cde_start_pos) {
Ok(result) => result,
Err(_) => return Self::get_directory_counts_zip32(footer, cde_start_pos)
};
Ok(result) => result,
Err(_) => return Self::get_directory_counts_zip32(footer, cde_start_pos),
};
// Check if it also has a zip32 footer
let (archive_offset_32, directory_start_32, number_of_files_32) =
match Self::get_directory_counts_zip32(footer, cde_start_pos) {
Ok(result) => result,
Err(_) => {
supported_64?;
return Ok((archive_offset_64, directory_start_64, number_of_files_64))
}
};
Ok(result) => result,
Err(_) => {
supported_64?;
return Ok((archive_offset_64, directory_start_64, number_of_files_64));
}
};
// It has both, so check if the zip64 footer is valid; if not, assume zip32
if archive_offset_64 < u32::MAX as u64 && archive_offset_64 != archive_offset_32
|| archive_offset_32 != u32::MAX as u64 {
|| archive_offset_32 != u32::MAX as u64
{
return Ok((archive_offset_32, directory_start_32, number_of_files_32));
}
if directory_start_64 < u32::MAX as u64 && directory_start_64 != directory_start_32
|| directory_start_32 != u32::MAX as u64 {
|| directory_start_32 != u32::MAX as u64
{
return Ok((archive_offset_32, directory_start_32, number_of_files_32));
}
if number_of_files_64 < u32::MAX as usize && number_of_files_64 != number_of_files_32
|| number_of_files_32 != u32::MAX as usize {
|| number_of_files_32 != u32::MAX as usize
{
return Ok((archive_offset_32, directory_start_32, number_of_files_32));
}
// It is, so we assume a zip64
supported_64?;
return Ok((archive_offset_64, directory_start_64, number_of_files_64))
Ok((archive_offset_64, directory_start_64, number_of_files_64))
}
/// Read a ZIP archive, collecting the files it contains

View file

@ -439,7 +439,6 @@ impl<W: Write + Seek> ZipWriter<W> {
{
let header_start = self.inner.get_plain().stream_position()?;
let name = name.into();
validate_name(&name)?;
let permissions = options.permissions.unwrap_or(0o100644);
let file = ZipFileData {
@ -1034,29 +1033,6 @@ impl<W: Write + Seek> ZipWriter<W> {
}
}
#[cfg_attr(fuzzing, visibility::make(pub))]
#[cfg_attr(fuzzing, allow(missing_docs))]
pub(crate) fn validate_name(name: &String) -> ZipResult<()> {
let bytes = name.as_bytes();
let mut current_window = [0u8; 4];
for window in bytes.windows(4) {
current_window.copy_from_slice(window);
let magic_number = u32::from_le_bytes(current_window);
match magic_number {
spec::ZIP64_CENTRAL_DIRECTORY_END_SIGNATURE => {
return Err(InvalidArchive("Filename can't contain ZIP64 end signature"));
}
spec::ZIP64_CENTRAL_DIRECTORY_END_LOCATOR_SIGNATURE => {
return Err(InvalidArchive(
"Filename can't contain ZIP64 end-locator signature",
));
}
_ => {}
}
}
Ok(())
}
impl<W: Write + Seek> Drop for ZipWriter<W> {
fn drop(&mut self) {
if !self.inner.is_closed() {