From 8193a4b1b2b8cee6f4ab978634f7df668b9618da Mon Sep 17 00:00:00 2001 From: Austin Abell Date: Mon, 30 Nov 2020 13:51:54 -0500 Subject: [PATCH] Implement hamt fuzzer (#872) * Implement hamt fuzzer * Change author --- ipld/hamt/fuzz/.gitignore | 5 +++ ipld/hamt/fuzz/Cargo.toml | 29 ++++++++++++++ ipld/hamt/fuzz/fuzz_targets/hamt_fuzz.rs | 49 ++++++++++++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 ipld/hamt/fuzz/.gitignore create mode 100644 ipld/hamt/fuzz/Cargo.toml create mode 100644 ipld/hamt/fuzz/fuzz_targets/hamt_fuzz.rs diff --git a/ipld/hamt/fuzz/.gitignore b/ipld/hamt/fuzz/.gitignore new file mode 100644 index 000000000000..e0fb40571e93 --- /dev/null +++ b/ipld/hamt/fuzz/.gitignore @@ -0,0 +1,5 @@ + +target +corpus +artifacts +Cargo.lock \ No newline at end of file diff --git a/ipld/hamt/fuzz/Cargo.toml b/ipld/hamt/fuzz/Cargo.toml new file mode 100644 index 000000000000..eb7eb943486b --- /dev/null +++ b/ipld/hamt/fuzz/Cargo.toml @@ -0,0 +1,29 @@ + +[package] +name = "ipld_hamt-fuzz" +version = "0.0.0" +authors = ["ChainSafe Systems "] +publish = false +edition = "2018" + +[package.metadata] +cargo-fuzz = true + +[dependencies] +libfuzzer-sys = "0.3" +arbitrary = { version = "0.4", features = ["derive"] } +ahash = "0.5" +db = { path = "../../../node/db" } + +[dependencies.ipld_hamt] +path = ".." + +# Prevent this from interfering with workspaces +[workspace] +members = ["."] + +[[bin]] +name = "hamt_fuzz" +path = "fuzz_targets/hamt_fuzz.rs" +test = false +doc = false diff --git a/ipld/hamt/fuzz/fuzz_targets/hamt_fuzz.rs b/ipld/hamt/fuzz/fuzz_targets/hamt_fuzz.rs new file mode 100644 index 000000000000..be074a492952 --- /dev/null +++ b/ipld/hamt/fuzz/fuzz_targets/hamt_fuzz.rs @@ -0,0 +1,49 @@ +#![no_main] +use arbitrary::Arbitrary; +use ipld_hamt::Hamt; +use libfuzzer_sys::fuzz_target; + +#[derive(Debug, Arbitrary)] +struct Operation { + key: u64, + method: Method, +} + +#[derive(Debug, Arbitrary)] +enum Method { + Insert(u64), + Remove, + Get, +} + +fuzz_target!(|data: (u8, Vec)| { + let (flush_rate, operations) = data; + let db = db::MemoryDB::default(); + let mut hamt = Hamt::<_, _, _>::new_with_bit_width(&db, 5); + let mut elements = ahash::AHashMap::new(); + + let flush_rate = (flush_rate as usize).saturating_add(5); + for (i, Operation { key, method }) in operations.into_iter().enumerate() { + if i % flush_rate == 0 { + // Periodic flushing of Hamt to fuzz blockstore usage also + hamt.flush().unwrap(); + } + + match method { + Method::Insert(v) => { + elements.insert(key, v); + hamt.set(key, v).unwrap(); + } + Method::Remove => { + let el = elements.remove(&key); + let hamt_deleted = hamt.delete(&key).unwrap().map(|(_, v)| v); + assert_eq!(hamt_deleted, el); + } + Method::Get => { + let ev = elements.get(&key); + let av = hamt.get(&key).unwrap(); + assert_eq!(av, ev); + } + } + } +});