From bf867c50126602f4d53ecf96ed641b8f32fbdafd Mon Sep 17 00:00:00 2001 From: Chris Hennick Date: Thu, 11 May 2023 19:25:32 -0700 Subject: [PATCH] Bug fix: skip invalid filenames during write fuzz --- Cargo.toml | 1 + fuzz/fuzz_targets/fuzz_write.rs | 3 +++ src/write.rs | 39 ++++++++++++++++++--------------- 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f8068edf..71717485 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/fuzz/fuzz_targets/fuzz_write.rs b/fuzz/fuzz_targets/fuzz_write.rs index ff495ffa..aa87278d 100644 --- a/fuzz/fuzz_targets/fuzz_write.rs +++ b/fuzz/fuzz_targets/fuzz_write.rs @@ -51,6 +51,9 @@ impl FileOperation { fn do_operation(writer: &mut RefCell>, operation: &FileOperation) -> Result<(), Box> 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::() >= u32::MAX as usize { diff --git a/src/write.rs b/src/write.rs index 622b39d2..7dfef832 100644 --- a/src/write.rs +++ b/src/write.rs @@ -439,7 +439,7 @@ impl ZipWriter { { 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 ZipWriter { 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::()?; - 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::()?; + 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 Drop for ZipWriter {