Skip to content

Commit 886c8d4

Browse files
put fuzz in same workspace!
1 parent 2c32f8a commit 886c8d4

File tree

4 files changed

+148
-59
lines changed

4 files changed

+148
-59
lines changed

Cargo.toml

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,17 @@ rustdoc-args = ["--cfg", "docsrs"]
2727
members = [
2828
".",
2929
"cli",
30+
"fuzz",
3031
]
3132
default-members = [
3233
".",
3334
]
3435
resolver = "2"
3536

3637
[workspace.dependencies]
38+
arbitrary = { version = "1.3.2", features = ["derive"] }
3739
time = { version = "0.3.36", default-features = false }
38-
zip = { path = "." }
40+
zip = { path = ".", default-features = false }
3941

4042
[dependencies]
4143
aes = { version = "0.8.4", optional = true }
@@ -65,7 +67,7 @@ lzma-rs = { version = "0.3.0", default-features = false, optional = true }
6567
crossbeam-utils = "0.8.20"
6668

6769
[target.'cfg(fuzzing)'.dependencies]
68-
arbitrary = { version = "1.3.2", features = ["derive"] }
70+
arbitrary.workspace = true
6971

7072
[dev-dependencies]
7173
bencher = "0.1.5"
@@ -117,5 +119,12 @@ harness = false
117119
# Reduce the size of the zip-cli binary.
118120
[profile.release]
119121
strip = true
120-
lto = true
122+
# This is necessary for fuzzing, which can only use dev or release profiles, and breaks if LTO
123+
# is specified.
124+
lto = false
121125
opt-level = "z"
126+
127+
[profile.release-lto]
128+
inherits = "release"
129+
# This slightly reduces the size of the output binary.
130+
lto = true

cli/Cargo.toml

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
[package]
22
name = "zip-cli"
3-
version = "0.0.0"
3+
version = "0.0.1"
44
authors = [
55
"Danny McClanahan <dmcC2@hypnicjerk.ai>",
66
]
77
license = "MIT"
88
repository = "https://github.com/zip-rs/zip2.git"
99
keywords = ["zip", "archive", "compression", "cli"]
1010
categories = ["command-line-utilities", "compression", "filesystem", "development-tools::build-utils"]
11-
rust-version = "1.73.0"
11+
# Keep this up to date with clap!
12+
rust-version = "1.74.0"
1213
description = """
1314
Binary for creation and manipulation of zip files.
1415
"""
@@ -18,7 +19,16 @@ edition = "2021"
1819
name = "zip-cli"
1920

2021
[dependencies]
21-
zip.workspace = true
22-
2322
clap = { version = "4.5.15", features = ["derive"] }
2423
eyre = "0.6"
24+
25+
[dependencies.zip]
26+
workspace = true
27+
features = [
28+
"bzip2",
29+
"deflate64",
30+
"deflate",
31+
"lzma",
32+
"zstd",
33+
"xz",
34+
]

fuzz/Cargo.toml

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,17 @@ edition = "2018"
99
cargo-fuzz = true
1010

1111
[dependencies]
12+
zip.workspace = true
13+
1214
libfuzzer-sys = "0.4"
13-
arbitrary = { version = "1.3.2", features = ["derive"] }
15+
arbitrary.workspace = true
1416
replace_with = "0.1.7"
1517
tikv-jemallocator = "0.6.0"
1618

17-
[dependencies.zip]
18-
path = ".."
19-
default-features = false
20-
2119
[features]
2220
zip_defaults = ["zip/default"]
2321
default = ["zip_defaults"]
2422

25-
# Prevent this from interfering with workspaces
26-
[workspace]
27-
members = ["."]
28-
2923
[[bin]]
3024
name = "fuzz_read"
3125
path = "fuzz_targets/fuzz_read.rs"

fuzz/fuzz_targets/fuzz_write.rs

Lines changed: 119 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
#![no_main]
22

33
use arbitrary::Arbitrary;
4-
use core::fmt::{Debug};
4+
use core::fmt::Debug;
55
use libfuzzer_sys::fuzz_target;
66
use replace_with::replace_with_or_abort;
77
use std::fmt::{Arguments, Formatter, Write};
8-
use std::io::{Cursor, Seek, SeekFrom};
98
use std::io::Write as IoWrite;
9+
use std::io::{Cursor, Seek, SeekFrom};
1010
use std::path::PathBuf;
1111
use tikv_jemallocator::Jemalloc;
1212
use zip::result::{ZipError, ZipResult};
@@ -93,22 +93,36 @@ fn do_operation<'k>(
9393
flush_on_finish_file: bool,
9494
files_added: &mut usize,
9595
stringifier: &mut impl Write,
96-
panic_on_error: bool
96+
panic_on_error: bool,
9797
) -> Result<(), Box<dyn std::error::Error>> {
9898
writer.set_flush_on_finish_file(flush_on_finish_file);
99-
let FileOperation { basic, mut path, reopen} = operation;
99+
let FileOperation {
100+
basic,
101+
mut path,
102+
reopen,
103+
} = operation;
100104
match basic {
101105
BasicFileOperation::WriteNormalFile {
102-
contents, mut options, ..
106+
contents,
107+
mut options,
108+
..
103109
} => {
104110
let uncompressed_size = contents.iter().map(|chunk| chunk.len()).sum::<usize>();
105111
if uncompressed_size >= u32::MAX as usize {
106112
options = options.large_file(true);
107113
}
108114
if options == FullFileOptions::default() {
109-
writeln!(stringifier, "writer.start_file_from_path({:?}, Default::default())?;", path)?;
115+
writeln!(
116+
stringifier,
117+
"writer.start_file_from_path({:?}, Default::default())?;",
118+
path
119+
)?;
110120
} else {
111-
writeln!(stringifier, "writer.start_file_from_path({:?}, {:?})?;", path, options)?;
121+
writeln!(
122+
stringifier,
123+
"writer.start_file_from_path({:?}, {:?})?;",
124+
path, options
125+
)?;
112126
}
113127
writer.start_file_from_path(&*path, options)?;
114128
for chunk in contents.iter() {
@@ -118,12 +132,20 @@ fn do_operation<'k>(
118132
*files_added += 1;
119133
}
120134
BasicFileOperation::WriteDirectory(options) => {
121-
writeln!(stringifier, "writer.add_directory_from_path(&{:?}, {:?})?;", path, options)?;
135+
writeln!(
136+
stringifier,
137+
"writer.add_directory_from_path(&{:?}, {:?})?;",
138+
path, options
139+
)?;
122140
writer.add_directory_from_path(&*path, options.to_owned())?;
123141
*files_added += 1;
124142
}
125143
BasicFileOperation::WriteSymlinkWithTarget { target, options } => {
126-
writeln!(stringifier, "writer.add_symlink_from_path(&{:?}, {:?}, {:?});", path, target, options)?;
144+
writeln!(
145+
stringifier,
146+
"writer.add_symlink_from_path(&{:?}, {:?}, {:?});",
147+
path, target, options
148+
)?;
127149
writer.add_symlink_from_path(&*path, target, options.to_owned())?;
128150
*files_added += 1;
129151
}
@@ -132,8 +154,20 @@ fn do_operation<'k>(
132154
return Ok(());
133155
};
134156
deduplicate_paths(&mut path, &base_path);
135-
do_operation(writer, *base, false, flush_on_finish_file, files_added, stringifier, panic_on_error)?;
136-
writeln!(stringifier, "writer.shallow_copy_file_from_path({:?}, {:?});", base_path, path)?;
157+
do_operation(
158+
writer,
159+
*base,
160+
false,
161+
flush_on_finish_file,
162+
files_added,
163+
stringifier,
164+
panic_on_error,
165+
)?;
166+
writeln!(
167+
stringifier,
168+
"writer.shallow_copy_file_from_path({:?}, {:?});",
169+
base_path, path
170+
)?;
137171
writer.shallow_copy_file_from_path(&*base_path, &*path)?;
138172
*files_added += 1;
139173
}
@@ -142,38 +176,65 @@ fn do_operation<'k>(
142176
return Ok(());
143177
};
144178
deduplicate_paths(&mut path, &base_path);
145-
do_operation(writer, *base, false, flush_on_finish_file, files_added, stringifier, panic_on_error)?;
146-
writeln!(stringifier, "writer.deep_copy_file_from_path({:?}, {:?});", base_path, path)?;
179+
do_operation(
180+
writer,
181+
*base,
182+
false,
183+
flush_on_finish_file,
184+
files_added,
185+
stringifier,
186+
panic_on_error,
187+
)?;
188+
writeln!(
189+
stringifier,
190+
"writer.deep_copy_file_from_path({:?}, {:?});",
191+
base_path, path
192+
)?;
147193
writer.deep_copy_file_from_path(&*base_path, path)?;
148194
*files_added += 1;
149195
}
150-
BasicFileOperation::MergeWithOtherFile { operations, initial_junk } => {
196+
BasicFileOperation::MergeWithOtherFile {
197+
operations,
198+
initial_junk,
199+
} => {
151200
if initial_junk.is_empty() {
152-
writeln!(stringifier, "let sub_writer = {{\n\
153-
let mut writer = ZipWriter::new(Cursor::new(Vec::new()));")?;
201+
writeln!(
202+
stringifier,
203+
"let sub_writer = {{\n\
204+
let mut writer = ZipWriter::new(Cursor::new(Vec::new()));"
205+
)?;
154206
} else {
155-
writeln!(stringifier,
156-
"let sub_writer = {{\n\
207+
writeln!(
208+
stringifier,
209+
"let sub_writer = {{\n\
157210
let mut initial_junk = Cursor::new(vec!{:?});\n\
158211
initial_junk.seek(SeekFrom::End(0))?;
159-
let mut writer = ZipWriter::new(initial_junk);", initial_junk)?;
212+
let mut writer = ZipWriter::new(initial_junk);",
213+
initial_junk
214+
)?;
160215
}
161216
let mut initial_junk = Cursor::new(initial_junk.into_vec());
162217
initial_junk.seek(SeekFrom::End(0))?;
163218
let mut other_writer = zip::ZipWriter::new(initial_junk);
164219
let mut inner_files_added = 0;
165-
operations.into_vec().into_iter().for_each(|(operation, abort)| {
166-
let _ = do_operation(
167-
&mut other_writer,
168-
operation,
169-
abort,
170-
false,
171-
&mut inner_files_added,
172-
stringifier,
173-
panic_on_error
174-
);
175-
});
176-
writeln!(stringifier, "writer\n}};\nwriter.merge_archive(sub_writer.finish_into_readable()?)?;")?;
220+
operations
221+
.into_vec()
222+
.into_iter()
223+
.for_each(|(operation, abort)| {
224+
let _ = do_operation(
225+
&mut other_writer,
226+
operation,
227+
abort,
228+
false,
229+
&mut inner_files_added,
230+
stringifier,
231+
panic_on_error,
232+
);
233+
});
234+
writeln!(
235+
stringifier,
236+
"writer\n}};\nwriter.merge_archive(sub_writer.finish_into_readable()?)?;"
237+
)?;
177238
writer.merge_archive(other_writer.finish_into_readable()?)?;
178239
*files_added += inner_files_added;
179240
}
@@ -193,15 +254,19 @@ fn do_operation<'k>(
193254
match reopen {
194255
ReopenOption::DoNotReopen => {
195256
writeln!(stringifier, "writer")?;
196-
return Ok(())
197-
},
257+
return Ok(());
258+
}
198259
ReopenOption::ViaFinish => {
199260
let old_comment = writer.get_raw_comment().to_owned();
200-
writeln!(stringifier, "let mut writer = ZipWriter::new_append(writer.finish()?)?;")?;
261+
writeln!(
262+
stringifier,
263+
"let mut writer = ZipWriter::new_append(writer.finish()?)?;"
264+
)?;
201265
replace_with_or_abort(writer, |old_writer: zip::ZipWriter<Cursor<Vec<u8>>>| {
202266
(|| -> ZipResult<zip::ZipWriter<Cursor<Vec<u8>>>> {
203267
zip::ZipWriter::new_append(old_writer.finish()?)
204-
})().unwrap_or_else(|_| {
268+
})()
269+
.unwrap_or_else(|_| {
205270
if panic_on_error {
206271
panic!("Failed to create new ZipWriter")
207272
}
@@ -214,11 +279,15 @@ fn do_operation<'k>(
214279
}
215280
ReopenOption::ViaFinishIntoReadable => {
216281
let old_comment = writer.get_raw_comment().to_owned();
217-
writeln!(stringifier, "let mut writer = ZipWriter::new_append(writer.finish()?)?;")?;
282+
writeln!(
283+
stringifier,
284+
"let mut writer = ZipWriter::new_append(writer.finish()?)?;"
285+
)?;
218286
replace_with_or_abort(writer, |old_writer| {
219287
(|| -> ZipResult<zip::ZipWriter<Cursor<Vec<u8>>>> {
220288
zip::ZipWriter::new_append(old_writer.finish()?)
221-
})().unwrap_or_else(|_| {
289+
})()
290+
.unwrap_or_else(|_| {
222291
if panic_on_error {
223292
panic!("Failed to create new ZipWriter")
224293
}
@@ -231,7 +300,7 @@ fn do_operation<'k>(
231300
Ok(())
232301
}
233302

234-
impl <'k> FuzzTestCase<'k> {
303+
impl<'k> FuzzTestCase<'k> {
235304
fn execute(self, stringifier: &mut impl Write, panic_on_error: bool) -> ZipResult<()> {
236305
let mut initial_junk = Cursor::new(self.initial_junk.into_vec());
237306
initial_junk.seek(SeekFrom::End(0))?;
@@ -253,7 +322,7 @@ impl <'k> FuzzTestCase<'k> {
253322
self.flush_on_finish_file,
254323
&mut files_added,
255324
stringifier,
256-
panic_on_error
325+
panic_on_error,
257326
);
258327
}
259328
if final_reopen {
@@ -265,14 +334,21 @@ impl <'k> FuzzTestCase<'k> {
265334
}
266335
}
267336

268-
impl <'k> Debug for FuzzTestCase<'k> {
337+
impl<'k> Debug for FuzzTestCase<'k> {
269338
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
270339
if self.initial_junk.is_empty() {
271-
writeln!(f, "let mut writer = ZipWriter::new(Cursor::new(Vec::new()));")?;
340+
writeln!(
341+
f,
342+
"let mut writer = ZipWriter::new(Cursor::new(Vec::new()));"
343+
)?;
272344
} else {
273-
writeln!(f, "let mut initial_junk = Cursor::new(vec!{:?});\n\
345+
writeln!(
346+
f,
347+
"let mut initial_junk = Cursor::new(vec!{:?});\n\
274348
initial_junk.seek(SeekFrom::End(0))?;\n\
275-
let mut writer = ZipWriter::new(initial_junk);", &self.initial_junk)?;
349+
let mut writer = ZipWriter::new(initial_junk);",
350+
&self.initial_junk
351+
)?;
276352
}
277353
let _ = self.clone().execute(f, false);
278354
Ok(())

0 commit comments

Comments
 (0)