Fix failing tests other than deflate64 bug 25
This commit is contained in:
parent
e23ba853d3
commit
5e03f43f9a
2 changed files with 51 additions and 47 deletions
82
src/read.rs
82
src/read.rs
|
@ -5,6 +5,7 @@ use crate::aes::{AesReader, AesReaderValid};
|
||||||
use crate::compression::CompressionMethod;
|
use crate::compression::CompressionMethod;
|
||||||
use crate::cp437::FromCp437;
|
use crate::cp437::FromCp437;
|
||||||
use crate::crc32::Crc32Reader;
|
use crate::crc32::Crc32Reader;
|
||||||
|
use crate::read::zip_archive::Shared;
|
||||||
use crate::result::{InvalidPassword, ZipError, ZipResult};
|
use crate::result::{InvalidPassword, ZipError, ZipResult};
|
||||||
use crate::spec;
|
use crate::spec;
|
||||||
use crate::types::{AesMode, AesVendorVersion, AtomicU64, DateTime, System, ZipFileData};
|
use crate::types::{AesMode, AesVendorVersion, AtomicU64, DateTime, System, ZipFileData};
|
||||||
|
@ -74,11 +75,10 @@ pub(crate) mod zip_archive {
|
||||||
pub struct ZipArchive<R> {
|
pub struct ZipArchive<R> {
|
||||||
pub(super) reader: R,
|
pub(super) reader: R,
|
||||||
pub(super) shared: Arc<Shared>,
|
pub(super) shared: Arc<Shared>,
|
||||||
pub(super) comment: Vec<u8>,
|
pub(super) comment: Arc<Vec<u8>>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::read::zip_archive::Shared;
|
|
||||||
pub use zip_archive::ZipArchive;
|
pub use zip_archive::ZipArchive;
|
||||||
|
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
|
@ -381,43 +381,45 @@ impl<R: Read + Seek> ZipArchive<R> {
|
||||||
.ok_or(ZipError::InvalidArchive(
|
.ok_or(ZipError::InvalidArchive(
|
||||||
"File cannot contain ZIP64 central directory end",
|
"File cannot contain ZIP64 central directory end",
|
||||||
))?;
|
))?;
|
||||||
while let Ok((footer64, archive_offset)) = spec::Zip64CentralDirectoryEnd::find_and_parse(
|
let search_results = spec::Zip64CentralDirectoryEnd::find_and_parse(
|
||||||
reader,
|
reader,
|
||||||
locator64.end_of_central_directory_offset,
|
locator64.end_of_central_directory_offset,
|
||||||
search_upper_bound,
|
search_upper_bound,
|
||||||
) {
|
)?;
|
||||||
|
search_results.into_iter().for_each(|(footer64, archive_offset)| {
|
||||||
results.push({
|
results.push({
|
||||||
let directory_start = footer64
|
let directory_start_result = footer64
|
||||||
.central_directory_offset
|
.central_directory_offset
|
||||||
.checked_add(archive_offset)
|
.checked_add(archive_offset)
|
||||||
.ok_or(ZipError::InvalidArchive(
|
.ok_or(ZipError::InvalidArchive(
|
||||||
"Invalid central directory size or offset",
|
"Invalid central directory size or offset",
|
||||||
))?;
|
|
||||||
if directory_start > search_upper_bound {
|
|
||||||
return Err(ZipError::InvalidArchive(
|
|
||||||
"Invalid central directory size or offset",
|
|
||||||
));
|
));
|
||||||
}
|
directory_start_result.and_then(|directory_start| {
|
||||||
if footer64.number_of_files_on_this_disk > footer64.number_of_files {
|
if directory_start > search_upper_bound {
|
||||||
return Err(ZipError::InvalidArchive(
|
Err(ZipError::InvalidArchive(
|
||||||
"ZIP64 footer indicates more files on this disk than in the whole archive",
|
"Invalid central directory size or offset",
|
||||||
));
|
))
|
||||||
}
|
} else if footer64.number_of_files_on_this_disk > footer64.number_of_files {
|
||||||
if footer64.version_needed_to_extract > footer64.version_made_by {
|
Err(ZipError::InvalidArchive(
|
||||||
return Err(ZipError::InvalidArchive(
|
"ZIP64 footer indicates more files on this disk than in the whole archive",
|
||||||
"ZIP64 footer indicates a new version is needed to extract this archive than the \
|
))
|
||||||
|
} else if footer64.version_needed_to_extract > footer64.version_made_by {
|
||||||
|
Err(ZipError::InvalidArchive(
|
||||||
|
"ZIP64 footer indicates a new version is needed to extract this archive than the \
|
||||||
version that wrote it",
|
version that wrote it",
|
||||||
));
|
))
|
||||||
}
|
} else {
|
||||||
Ok(CentralDirectoryInfo {
|
Ok(CentralDirectoryInfo {
|
||||||
archive_offset,
|
archive_offset,
|
||||||
directory_start,
|
directory_start,
|
||||||
number_of_files: footer64.number_of_files as usize,
|
number_of_files: footer64.number_of_files as usize,
|
||||||
disk_number: footer64.disk_number,
|
disk_number: footer64.disk_number,
|
||||||
disk_with_central_directory: footer64.disk_with_central_directory,
|
disk_with_central_directory: footer64.disk_with_central_directory,
|
||||||
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
Ok(results)
|
Ok(results)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -480,25 +482,23 @@ impl<R: Read + Seek> ZipArchive<R> {
|
||||||
};
|
};
|
||||||
let mut files = Vec::with_capacity(file_capacity);
|
let mut files = Vec::with_capacity(file_capacity);
|
||||||
let mut names_map = HashMap::with_capacity(file_capacity);
|
let mut names_map = HashMap::with_capacity(file_capacity);
|
||||||
|
let dir_end = reader.seek(io::SeekFrom::Start(dir_info.directory_start))?;
|
||||||
for _ in 0..dir_info.number_of_files {
|
for _ in 0..dir_info.number_of_files {
|
||||||
let file = central_header_to_zip_file(reader, dir_info.archive_offset)?;
|
let file = central_header_to_zip_file(reader, dir_info.archive_offset)?;
|
||||||
names_map.insert(file.file_name.clone(), files.len());
|
names_map.insert(file.file_name.clone(), files.len());
|
||||||
files.push(file);
|
files.push(file);
|
||||||
}
|
}
|
||||||
let dir_end = reader.seek(io::SeekFrom::Start(dir_info.directory_start))?;
|
|
||||||
if dir_info.disk_number != dir_info.disk_with_central_directory {
|
if dir_info.disk_number != dir_info.disk_with_central_directory {
|
||||||
return unsupported_zip_error(
|
unsupported_zip_error("Support for multi-disk files is not implemented")
|
||||||
"Support for multi-disk files is not implemented",
|
} else {
|
||||||
);
|
Ok(Shared {
|
||||||
|
files,
|
||||||
|
names_map,
|
||||||
|
offset: dir_info.archive_offset,
|
||||||
|
dir_start: dir_info.directory_start,
|
||||||
|
dir_end,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
Ok(Shared {
|
|
||||||
files,
|
|
||||||
names_map,
|
|
||||||
offset: dir_info.archive_offset,
|
|
||||||
dir_start: dir_info.directory_start,
|
|
||||||
dir_end,
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.for_each(|result| match result {
|
.for_each(|result| match result {
|
||||||
|
@ -530,8 +530,8 @@ impl<R: Read + Seek> ZipArchive<R> {
|
||||||
let shared = Self::get_metadata(&mut reader, &footer, cde_start_pos)?;
|
let shared = Self::get_metadata(&mut reader, &footer, cde_start_pos)?;
|
||||||
Ok(ZipArchive {
|
Ok(ZipArchive {
|
||||||
reader,
|
reader,
|
||||||
shared: Arc::new(shared),
|
shared: shared.into(),
|
||||||
comment: footer.zip_file_comment,
|
comment: footer.zip_file_comment.into(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/// Extract a Zip archive into a directory, overwriting files if they
|
/// Extract a Zip archive into a directory, overwriting files if they
|
||||||
|
|
16
src/spec.rs
16
src/spec.rs
|
@ -145,7 +145,8 @@ impl Zip64CentralDirectoryEnd {
|
||||||
reader: &mut T,
|
reader: &mut T,
|
||||||
nominal_offset: u64,
|
nominal_offset: u64,
|
||||||
search_upper_bound: u64,
|
search_upper_bound: u64,
|
||||||
) -> ZipResult<(Zip64CentralDirectoryEnd, u64)> {
|
) -> ZipResult<Vec<(Zip64CentralDirectoryEnd, u64)>> {
|
||||||
|
let mut results = Vec::new();
|
||||||
let mut pos = search_upper_bound;
|
let mut pos = search_upper_bound;
|
||||||
|
|
||||||
while pos >= nominal_offset {
|
while pos >= nominal_offset {
|
||||||
|
@ -166,7 +167,7 @@ impl Zip64CentralDirectoryEnd {
|
||||||
let central_directory_size = reader.read_u64::<LittleEndian>()?;
|
let central_directory_size = reader.read_u64::<LittleEndian>()?;
|
||||||
let central_directory_offset = reader.read_u64::<LittleEndian>()?;
|
let central_directory_offset = reader.read_u64::<LittleEndian>()?;
|
||||||
|
|
||||||
return Ok((
|
results.push((
|
||||||
Zip64CentralDirectoryEnd {
|
Zip64CentralDirectoryEnd {
|
||||||
version_made_by,
|
version_made_by,
|
||||||
version_needed_to_extract,
|
version_needed_to_extract,
|
||||||
|
@ -186,10 +187,13 @@ impl Zip64CentralDirectoryEnd {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if results.is_empty() {
|
||||||
Err(ZipError::InvalidArchive(
|
Err(ZipError::InvalidArchive(
|
||||||
"Could not find ZIP64 central directory end",
|
"Could not find ZIP64 central directory end",
|
||||||
))
|
))
|
||||||
|
} else {
|
||||||
|
Ok(results)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write<T: Write>(&self, writer: &mut T) -> ZipResult<()> {
|
pub fn write<T: Write>(&self, writer: &mut T) -> ZipResult<()> {
|
||||||
|
|
Loading…
Add table
Reference in a new issue