fix: Overflow panic when central directory extra data is too large
This commit is contained in:
parent
5ae025e2cb
commit
2a035f5201
2 changed files with 42 additions and 6 deletions
12
src/types.rs
12
src/types.rs
|
@ -803,13 +803,13 @@ impl ZipFileData {
|
|||
})
|
||||
}
|
||||
|
||||
pub(crate) fn block(&self, zip64_extra_field_length: u16) -> ZipCentralEntryBlock {
|
||||
pub(crate) fn block(&self, zip64_extra_field_length: u16) -> ZipResult<ZipCentralEntryBlock> {
|
||||
let extra_field_len: u16 = self.extra_field_len().try_into().unwrap();
|
||||
let central_extra_field_len: u16 = self.central_extra_field_len().try_into().unwrap();
|
||||
let last_modified_time = self
|
||||
.last_modified_time
|
||||
.unwrap_or_else(DateTime::default_for_write);
|
||||
ZipCentralEntryBlock {
|
||||
Ok(ZipCentralEntryBlock {
|
||||
magic: ZipCentralEntryBlock::MAGIC,
|
||||
version_made_by: (self.system as u16) << 8
|
||||
| (self.version_made_by as u16).max(self.version_needed()),
|
||||
|
@ -831,8 +831,10 @@ impl ZipFileData {
|
|||
.unwrap(),
|
||||
file_name_length: self.file_name_raw.len().try_into().unwrap(),
|
||||
extra_field_length: zip64_extra_field_length
|
||||
+ extra_field_len
|
||||
+ central_extra_field_len,
|
||||
.checked_add(extra_field_len + central_extra_field_len)
|
||||
.ok_or(ZipError::InvalidArchive(
|
||||
"Extra field length in central directory exceeds 64KiB",
|
||||
))?,
|
||||
file_comment_length: self.file_comment.as_bytes().len().try_into().unwrap(),
|
||||
disk_number: 0,
|
||||
internal_file_attributes: 0,
|
||||
|
@ -842,7 +844,7 @@ impl ZipFileData {
|
|||
.min(spec::ZIP64_BYTES_THR)
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn zip64_extra_field_block(&self) -> Option<Zip64ExtraFieldBlock> {
|
||||
|
|
36
src/write.rs
36
src/write.rs
|
@ -1875,7 +1875,7 @@ fn write_central_directory_header<T: Write>(writer: &mut T, file: &ZipFileData)
|
|||
let mut zip64_extra_field = [0; 28];
|
||||
let zip64_extra_field_length =
|
||||
write_central_zip64_extra_field(&mut zip64_extra_field.as_mut(), file)?;
|
||||
let block = file.block(zip64_extra_field_length);
|
||||
let block = file.block(zip64_extra_field_length)?;
|
||||
block.write(writer)?;
|
||||
// file name
|
||||
writer.write_all(&file.file_name_raw)?;
|
||||
|
@ -2839,4 +2839,38 @@ mod test {
|
|||
let _ = writer.finish_into_readable()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "_deflate-any", feature = "aes-crypto"))]
|
||||
#[test]
|
||||
fn test_fuzz_crash_2024_06_14d() -> ZipResult<()> {
|
||||
use crate::write::EncryptWith::Aes;
|
||||
use crate::AesMode::Aes256;
|
||||
use CompressionMethod::Deflated;
|
||||
let mut writer = ZipWriter::new(Cursor::new(Vec::new()));
|
||||
writer.set_flush_on_finish_file(false);
|
||||
let options = FileOptions {
|
||||
compression_method: Deflated,
|
||||
compression_level: Some(5),
|
||||
last_modified_time: DateTime::from_date_and_time(2107, 4, 8, 15, 54, 19)?,
|
||||
permissions: None,
|
||||
large_file: true,
|
||||
encrypt_with: Some(Aes {
|
||||
mode: Aes256,
|
||||
password: "",
|
||||
}),
|
||||
extended_options: ExtendedFileOptions {
|
||||
extra_data: vec![2, 0, 1, 0, 0].into(),
|
||||
central_extra_data: vec![
|
||||
35, 229, 2, 0, 41, 41, 231, 44, 2, 0, 52, 233, 82, 201, 0, 0, 3, 0, 2, 0, 233,
|
||||
255, 3, 0, 2, 0, 26, 154, 38, 251, 0, 0,
|
||||
]
|
||||
.into(),
|
||||
},
|
||||
alignment: 65535,
|
||||
zopfli_buffer_size: None,
|
||||
};
|
||||
writer.add_directory_from_path("", options)?;
|
||||
let _ = writer.finish_into_readable()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue