diff --git a/Makefile b/Makefile index f6375f69a..7c4abc527 100644 --- a/Makefile +++ b/Makefile @@ -59,6 +59,17 @@ docs: cd docs && mdbook serve --open FUZZER = field_from_hex -run-fuzzer: - cd fuzz - cargo +nightly fuzz run $(FUZZER) +run-no-gpu-fuzzer: + cd fuzz/no_gpu_fuzz + cargo +nightly fuzz run --fuzz-dir . $(FUZZER) + +METALFUZZER = fft_diff +run-metal-fuzzer: + cd fuzz/metal_fuzz + cargo +nightly fuzz run --fuzz-dir . $(METALFUZZER) + +CUDAFUZZER = cuda_fft_fuzzer +run-cuda-fuzzer: + cd fuzzer + cargo hfuzz run $(CUDAFUZZER) + diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 74cdd8c8c..a213eff98 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -1,58 +1,16 @@ -[package] -name = "fuzz" +[workspace] +members = ["no_gpu_fuzz", "metal_fuzz", "cuda_fuzz"] + +[workspace.package] +edition = "2021" publish = false version = "0.1.1" -edition = "2021" - -[package.metadata] -cargo-fuzz = true -[dependencies] +[workspace.dependencies] +lambdaworks-math = { path = "../math" } +lambdaworks-gpu = { path = "../gpu" } libfuzzer-sys = "0.4" -lambdaworks-math = { path = "../math", features = ["metal"] } -lambdaworks-gpu = { path = "../gpu", features = ["metal"] } -num-traits = "0.2" -ibig = "0.3.6" - -# Prevent this from interfering with workspaces -[workspace] -members = ["."] [profile.release] debug = 1 -[[bin]] -name = "field_fuzzer" -path = "fuzz_targets/field_fuzzer.rs" -test = false -doc = false - -[[bin]] -name = "field_from_hex" -path = "fuzz_targets/field_from_hex.rs" -test = false -doc = false - -[[bin]] -name = "field_from_raw" -path = "fuzz_targets/field_from_raw.rs" -test = false -doc = false - -[[bin]] -name = "metal_fft_diff" -path = "fuzz_targets/metal_fft_diff.rs" -test = false -doc = false - -[[bin]] -name = "polynomial_fft_diff_fuzzer" -path = "fuzz_targets/polynomial_fft_diff_fuzzer.rs" -test = false -doc = false - -[[bin]] -name = "twiddles_generation" -path = "fuzz_targets/twiddles_generation.rs" -test = false -doc = false diff --git a/fuzz/README.md b/fuzz/README.md index 2839640e8..abc0601be 100644 --- a/fuzz/README.md +++ b/fuzz/README.md @@ -1,9 +1,10 @@ # Fuzzing +There are three types of fuzzers distributed on different workspaces depending on the features (metal/cuda) they need. So you should make sure you cded into the right folder before running any of the commands. ### Running the fuzzers -`cargo +nightly fuzz run ` +`cargo +nightly fuzz run --fuzz-dir . ` The targets can be found in the `fuzz_targets` directory. Normally the name of the file without the extension should work, if it doesn't, look up the name for that binary target in `Cargo.toml`. ### Debugging If a crash is found, an `artifacts/` folder will be added, inside it you'll find the different reports. To get an lldb dump, run -`cargo +nightly fuzz run artifacts/crash-xxx` +`cargo +nightly fuzz run --fuzz-dir . artifacts/crash-xxx` diff --git a/fuzz/metal_fuzz/Cargo.toml b/fuzz/metal_fuzz/Cargo.toml new file mode 100644 index 000000000..b15d71947 --- /dev/null +++ b/fuzz/metal_fuzz/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "metal_fuzz" +version.workspace = true +edition.workspace = true + +[package.metadata] +cargo-fuzz = true + +[dependencies] +lambdaworks-math = { workspace = true, features = ["metal"] } +lambdaworks-gpu = { workspace = true, features = ["metal"] } +libfuzzer-sys = { workspace = true } + +[[bin]] +name = "fft_diff" +path = "fuzz_targets/fft_diff.rs" +test = false +doc = false + +[[bin]] +name = "polynomial_fft_diff" +path = "fuzz_targets/polynomial_fft_diff.rs" +test = false +doc = false + +[[bin]] +name = "twiddles_generation_diff" +path = "fuzz_targets/twiddles_generation_diff.rs" +test = false +doc = false + diff --git a/fuzz/fuzz_targets/metal_fft_diff.rs b/fuzz/metal_fuzz/fuzz_targets/fft_diff.rs similarity index 100% rename from fuzz/fuzz_targets/metal_fft_diff.rs rename to fuzz/metal_fuzz/fuzz_targets/fft_diff.rs diff --git a/fuzz/fuzz_targets/polynomial_fft_diff_fuzzer.rs b/fuzz/metal_fuzz/fuzz_targets/polynomial_fft_diff.rs similarity index 97% rename from fuzz/fuzz_targets/polynomial_fft_diff_fuzzer.rs rename to fuzz/metal_fuzz/fuzz_targets/polynomial_fft_diff.rs index d5238908b..e35137cc6 100644 --- a/fuzz/fuzz_targets/polynomial_fft_diff_fuzzer.rs +++ b/fuzz/metal_fuzz/fuzz_targets/polynomial_fft_diff.rs @@ -9,8 +9,7 @@ use lambdaworks_math::{ field::{ fields::fft_friendly::stark_252_prime_field::Stark252PrimeField, element::FieldElement, - }, - unsigned_integer::element::UnsignedInteger + } }; use lambdaworks_gpu::metal::abstractions::errors::MetalError; diff --git a/fuzz/fuzz_targets/twiddles_generation.rs b/fuzz/metal_fuzz/fuzz_targets/twiddles_generation_diff.rs similarity index 100% rename from fuzz/fuzz_targets/twiddles_generation.rs rename to fuzz/metal_fuzz/fuzz_targets/twiddles_generation_diff.rs diff --git a/fuzz/no_gpu_fuzz/Cargo.toml b/fuzz/no_gpu_fuzz/Cargo.toml new file mode 100644 index 000000000..f45a36907 --- /dev/null +++ b/fuzz/no_gpu_fuzz/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "no_gpu_fuzz" +version.workspace = true +edition.workspace = true + +[package.metadata] +cargo-fuzz = true + +[dependencies] +lambdaworks-math = { workspace = true } +lambdaworks-gpu = { workspace = true } +libfuzzer-sys = { workspace = true } +num-traits = "0.2" +ibig = "0.3.6" + +[[bin]] +name = "field_fuzzer" +path = "fuzz_targets/field_fuzzer.rs" +test = false +doc = false + +[[bin]] +name = "field_from_hex" +path = "fuzz_targets/field_from_hex.rs" +test = false +doc = false + +[[bin]] +name = "field_from_raw" +path = "fuzz_targets/field_from_raw.rs" +test = false +doc = false + diff --git a/fuzz/fuzz_targets/field_from_hex.rs b/fuzz/no_gpu_fuzz/fuzz_targets/field_from_hex.rs similarity index 100% rename from fuzz/fuzz_targets/field_from_hex.rs rename to fuzz/no_gpu_fuzz/fuzz_targets/field_from_hex.rs diff --git a/fuzz/fuzz_targets/field_from_raw.rs b/fuzz/no_gpu_fuzz/fuzz_targets/field_from_raw.rs similarity index 91% rename from fuzz/fuzz_targets/field_from_raw.rs rename to fuzz/no_gpu_fuzz/fuzz_targets/field_from_raw.rs index 73fd809cd..3edcd5e35 100644 --- a/fuzz/fuzz_targets/field_from_raw.rs +++ b/fuzz/no_gpu_fuzz/fuzz_targets/field_from_raw.rs @@ -21,16 +21,16 @@ fuzz_target!(|values: (u64, u64)| { let a = FieldElement::::from_raw(&value_a); let b = FieldElement::::from_raw(&value_b); - let a_expected = ring.from(value_u64_a); - let b_expected = ring.from(value_u64_b); + let _a_expected = ring.from(value_u64_a); + let _b_expected = ring.from(value_u64_b); - let add_u64 = &a + &b; + let _add_u64 = &a + &b; - let sub_u64 = &a - &b; + let _sub_u64 = &a - &b; - let mul_u64 = &a * &b; + let _mul_u64 = &a * &b; - let pow = &a.pow(b.representative()); + let _pow = &a.pow(b.representative()); if value_u64_b != 0 { diff --git a/fuzz/fuzz_targets/field_fuzzer.rs b/fuzz/no_gpu_fuzz/fuzz_targets/field_fuzzer.rs similarity index 100% rename from fuzz/fuzz_targets/field_fuzzer.rs rename to fuzz/no_gpu_fuzz/fuzz_targets/field_fuzzer.rs diff --git a/fuzzer/Cargo.toml b/fuzzer/Cargo.toml new file mode 100644 index 000000000..4a811f13c --- /dev/null +++ b/fuzzer/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "fuzzer" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +honggfuzz = "0.5.51" +lambdaworks-math = { path = "../math", features = ["cuda"] } +lambdaworks-gpu = { path = "../gpu", features = ["cuda"] } + + +[workspace] +members = ["."] + +[[bin]] +name = "cuda_fft_fuzzer" +path = "src/cuda_fft_fuzzer.rs" diff --git a/fuzzer/README.md b/fuzzer/README.md new file mode 100644 index 000000000..6d34ee5c9 --- /dev/null +++ b/fuzzer/README.md @@ -0,0 +1,13 @@ +## Setup +Run the following commands to get ready the setup. + +* `cargo install honggfuzz ` +* `apt install build-essential` +* `apt-get install binutils-dev` +* `sudo apt-get install libunwind-dev` +* `sudo apt-get install lldb` + +## Run the fuzzer + +Run the following command to run the specific fuzzer +`cargo hfuzz run ` diff --git a/fuzzer/src/cuda_fft_fuzzer.rs b/fuzzer/src/cuda_fft_fuzzer.rs new file mode 100644 index 000000000..c46e73672 --- /dev/null +++ b/fuzzer/src/cuda_fft_fuzzer.rs @@ -0,0 +1,53 @@ +#[macro_use] +extern crate honggfuzz; +use lambdaworks_math::{ + fft::{ + gpu::cuda::{ops::fft as fft_cuda, state::CudaState}, + cpu::{ + roots_of_unity::get_twiddles, + ops::fft as fft_cpu + } + }, + field::{ + traits::RootsConfig, + fields::fft_friendly::stark_252_prime_field::Stark252PrimeField, + element::FieldElement + }, +}; + +fn main() { + loop { + fuzz!(|data: Vec| { + let mut input_raw = data; + let mut inputs = Vec::new(); + + if input_raw.len() == 0 { + input_raw.push(0u64); + } + + while !input_raw.len().is_power_of_two(){ + input_raw.push(input_raw[0]); + } + + for i in 0..input_raw.len() { + let input_value = format!("{:x}", input_raw[i]); + inputs.push(FieldElement::::from_hex_unchecked(&input_value)) + } + + let twiddles = get_twiddles( + inputs.len().trailing_zeros() as u64, + RootsConfig::BitReverse, + ) + .unwrap(); + + let state = CudaState::new().unwrap(); + println!("inputs {:?}", &inputs); + println!("fft cpu{:?}", fft_cpu(&inputs, &twiddles)); + + match fft_cpu(&inputs, &twiddles) { + Ok(fft_result) => assert_eq!(fft_result, fft_cuda(&inputs, &twiddles, &state).unwrap()), + Err(_) => assert!(fft_cuda(&inputs, &twiddles, &state).is_err()) + } + }); + } +}