Bug fix: skip invalid filenames during write fuzz

This commit is contained in:
Chris Hennick 2023-05-11 19:25:32 -07:00
parent dc351196e2
commit bf867c5012
No known key found for this signature in database
GPG key ID: 25653935CC8B6C74
3 changed files with 25 additions and 18 deletions

View file

@ -24,6 +24,7 @@ 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,6 +51,9 @@ 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

@ -439,7 +439,7 @@ impl<W: Write + Seek> ZipWriter<W> {
{
let header_start = self.inner.get_plain().stream_position()?;
let name = name.into();
Self::validate_name(&name)?;
validate_name(&name)?;
let permissions = options.permissions.unwrap_or(0o100644);
let file = ZipFileData {
@ -1032,27 +1032,30 @@ impl<W: Write + Seek> ZipWriter<W> {
self.insert_file_data(dest_data)?;
Ok(())
}
fn validate_name(name: &String) -> ZipResult<()> {
for (index, _) in name.match_indices("PK") {
if name.len() >= index + 4 {
let magic_number = name[index..index + 4]
.as_bytes()
.read_u32::<LittleEndian>()?;
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",
));
}
_ => {}
}
#[cfg_attr(fuzzing, visibility::make(pub))]
#[cfg_attr(fuzzing, allow(missing_docs))]
pub(crate) fn validate_name(name: &String) -> ZipResult<()> {
for (index, _) in name.match_indices("PK") {
if name.len() >= index + 4 {
let magic_number = name[index..index + 4]
.as_bytes()
.read_u32::<LittleEndian>()?;
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(())
}
Ok(())
}
impl<W: Write + Seek> Drop for ZipWriter<W> {