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 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 central_extra_field_len: u16 = self.central_extra_field_len().try_into().unwrap();
|
||||||
let last_modified_time = self
|
let last_modified_time = self
|
||||||
.last_modified_time
|
.last_modified_time
|
||||||
.unwrap_or_else(DateTime::default_for_write);
|
.unwrap_or_else(DateTime::default_for_write);
|
||||||
ZipCentralEntryBlock {
|
Ok(ZipCentralEntryBlock {
|
||||||
magic: ZipCentralEntryBlock::MAGIC,
|
magic: ZipCentralEntryBlock::MAGIC,
|
||||||
version_made_by: (self.system as u16) << 8
|
version_made_by: (self.system as u16) << 8
|
||||||
| (self.version_made_by as u16).max(self.version_needed()),
|
| (self.version_made_by as u16).max(self.version_needed()),
|
||||||
|
@ -831,8 +831,10 @@ impl ZipFileData {
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
file_name_length: self.file_name_raw.len().try_into().unwrap(),
|
file_name_length: self.file_name_raw.len().try_into().unwrap(),
|
||||||
extra_field_length: zip64_extra_field_length
|
extra_field_length: zip64_extra_field_length
|
||||||
+ extra_field_len
|
.checked_add(extra_field_len + central_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(),
|
file_comment_length: self.file_comment.as_bytes().len().try_into().unwrap(),
|
||||||
disk_number: 0,
|
disk_number: 0,
|
||||||
internal_file_attributes: 0,
|
internal_file_attributes: 0,
|
||||||
|
@ -842,7 +844,7 @@ impl ZipFileData {
|
||||||
.min(spec::ZIP64_BYTES_THR)
|
.min(spec::ZIP64_BYTES_THR)
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn zip64_extra_field_block(&self) -> Option<Zip64ExtraFieldBlock> {
|
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 mut zip64_extra_field = [0; 28];
|
||||||
let zip64_extra_field_length =
|
let zip64_extra_field_length =
|
||||||
write_central_zip64_extra_field(&mut zip64_extra_field.as_mut(), file)?;
|
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)?;
|
block.write(writer)?;
|
||||||
// file name
|
// file name
|
||||||
writer.write_all(&file.file_name_raw)?;
|
writer.write_all(&file.file_name_raw)?;
|
||||||
|
@ -2839,4 +2839,38 @@ mod test {
|
||||||
let _ = writer.finish_into_readable()?;
|
let _ = writer.finish_into_readable()?;
|
||||||
Ok(())
|
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