diff --git a/fuzz/.gitignore b/fuzz/.gitignore new file mode 100644 index 0000000..1a45eee --- /dev/null +++ b/fuzz/.gitignore @@ -0,0 +1,4 @@ +target +corpus +artifacts +coverage diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml new file mode 100644 index 0000000..52ebde0 --- /dev/null +++ b/fuzz/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "sliceslice-fuzz" +version = "0.0.0" +publish = false +edition = "2021" + +[package.metadata] +cargo-fuzz = true + +[dependencies] +arbitrary = { version = "1.3.0", features = ["derive"] } +libfuzzer-sys = "0.4" +sliceslice = { version = "0.4.1", path = ".." } + +# Prevent this from interfering with workspaces +[workspace] +members = ["."] + +[profile.release] +debug = 1 + +[[bin]] +name = "dynamic_avx2" +path = "fuzz_targets/dynamic_avx2.rs" +test = false +doc = false diff --git a/fuzz/fuzz_targets/dynamic_avx2.rs b/fuzz/fuzz_targets/dynamic_avx2.rs new file mode 100644 index 0000000..9e5a5e5 --- /dev/null +++ b/fuzz/fuzz_targets/dynamic_avx2.rs @@ -0,0 +1,33 @@ +#![no_main] + +use arbitrary::Arbitrary; +use libfuzzer_sys::fuzz_target; +use sliceslice::x86::DynamicAvx2Searcher; + +#[derive(Arbitrary, Debug)] +struct FuzzInput<'a> { + needle: &'a [u8], + haystack: &'a [u8], + position: usize, +} + +fuzz_target!(|input: FuzzInput<'_>| { + let mut input = input; + + // This is a documented panic, so avoid it + if !input.needle.is_empty() { + input.position %= input.needle.len(); + } + + let result = unsafe { + let searcher = DynamicAvx2Searcher::with_position(input.needle, input.position); + searcher.search_in(input.haystack) + }; + + let expected = match input.needle.len() { + 0 => true, + len => input.haystack.windows(len).any(|w| w == input.needle), + }; + + assert_eq!(result, expected); +});