diff --git a/Cargo.lock b/Cargo.lock index 803d530d041..1f08c8a657f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3516,12 +3516,7 @@ version = "1.0.0-beta.4" dependencies = [ "acvm", "bn254_blackbox_solver", - "cfg-if", - "chrono", - "env_logger", - "fxhash", "im", - "iter-extended", "libfuzzer-sys", "log", "nargo", @@ -3530,21 +3525,8 @@ dependencies = [ "noirc_errors", "noirc_evaluator", "noirc_frontend", - "num-bigint", - "num-traits", - "proptest", "rand", - "rayon", - "serde", - "serde_json", - "serde_with", - "similar-asserts", - "smallvec", - "test-case", "thiserror 1.0.69", - "tracing", - "tracing-test", - "vec-collections", ] [[package]] diff --git a/tooling/ast_fuzzer/src/input/mod.rs b/tooling/ast_fuzzer/src/input/mod.rs index 80c806771c6..2a2ceb7b2d3 100644 --- a/tooling/ast_fuzzer/src/input/mod.rs +++ b/tooling/ast_fuzzer/src/input/mod.rs @@ -77,7 +77,7 @@ fn arb_value_from_abi_type( IntStrategy::new(width as usize) .prop_map(move |mut int| { if int < 0 { - int += shift + int += shift; } InputValue::Field(int.into()) }) diff --git a/tooling/ast_fuzzer/src/lib.rs b/tooling/ast_fuzzer/src/lib.rs index 88a263f124d..4de189661f1 100644 --- a/tooling/ast_fuzzer/src/lib.rs +++ b/tooling/ast_fuzzer/src/lib.rs @@ -1,3 +1,7 @@ +#![forbid(unsafe_code)] +#![warn(clippy::semicolon_if_nothing_returned)] +#![cfg_attr(not(test), warn(unused_crate_dependencies, unused_extern_crates))] + mod abi; pub mod compare; mod input; diff --git a/tooling/ast_fuzzer/src/program/func.rs b/tooling/ast_fuzzer/src/program/func.rs index 84a2e64ff10..3119405527c 100644 --- a/tooling/ast_fuzzer/src/program/func.rs +++ b/tooling/ast_fuzzer/src/program/func.rs @@ -635,7 +635,7 @@ impl<'a> FunctionContext<'a> { if types::is_unit(typ) && u.ratio(4, 5)? { // ending a unit block with `;` looks better than a `()` but both are valid. // NB the AST printer puts a `;` between all statements, including after `if` and `for`. - stmts.push(Expression::Semi(Box::new(self.gen_stmt(u)?))) + stmts.push(Expression::Semi(Box::new(self.gen_stmt(u)?))); } else { stmts.push(self.gen_expr(u, typ, max_depth, Flags::TOP)?); } diff --git a/tooling/ast_fuzzer/src/program/visitor.rs b/tooling/ast_fuzzer/src/program/visitor.rs index 33d717773f6..26eb8f4181c 100644 --- a/tooling/ast_fuzzer/src/program/visitor.rs +++ b/tooling/ast_fuzzer/src/program/visitor.rs @@ -167,7 +167,7 @@ pub fn visit_expr(expr: &Expression, v: &mut V) where V: FnMut(&Expression) -> bool, { - visit_expr_be(expr, &mut |e| (v(e), ()), &mut |_, _| {}) + visit_expr_be(expr, &mut |e| (v(e), ()), &mut |_, _| {}); } /// Visit the contents of an [Expression] representing the AST, @@ -293,7 +293,7 @@ where Expression::Continue => {} } - e(expr, token) + e(expr, token); } fn visit_lvalue(lvalue: &LValue, b: &mut B, e: &mut E) diff --git a/tooling/greybox_fuzzer/Cargo.toml b/tooling/greybox_fuzzer/Cargo.toml index eae1f1ffb44..9172237f8f2 100644 --- a/tooling/greybox_fuzzer/Cargo.toml +++ b/tooling/greybox_fuzzer/Cargo.toml @@ -23,9 +23,11 @@ rand.workspace = true num-traits.workspace = true fm.workspace=true rayon.workspace = true -num-bigint.workspace = true rand_xorshift="0.3.0" walkdir = "2.5.0" sha256={ version = "1.5.0", default-features = false } termcolor = "1.1.2" + +[dev-dependencies] +num-bigint.workspace = true diff --git a/tooling/greybox_fuzzer/src/corpus.rs b/tooling/greybox_fuzzer/src/corpus.rs index 389538ba2ac..9612cbdbc1e 100644 --- a/tooling/greybox_fuzzer/src/corpus.rs +++ b/tooling/greybox_fuzzer/src/corpus.rs @@ -193,12 +193,12 @@ impl Sequence { /// Resets the sequence by setting remaining executions to 0 pub fn clear(&mut self) { - self.executions_left = 0 + self.executions_left = 0; } /// Decrements the number of remaining executions by 1 pub fn decrement(&mut self) { - self.executions_left -= 1 + self.executions_left -= 1; } } @@ -377,7 +377,7 @@ impl Corpus { self.corpus_file_manager.save_testcase_to_disk( &serialize_to_json(&new_testcase_value, &self.corpus_file_manager.abi) .expect("Shouldn't be any issues with serializing input map"), - )? + )?; } self.brillig_orchestrator.new_testcase(testcase_id); self.acir_orchestrator.new_testcase(testcase_id); diff --git a/tooling/greybox_fuzzer/src/dictionary.rs b/tooling/greybox_fuzzer/src/dictionary.rs index bbda0e2606d..824527ed4c5 100644 --- a/tooling/greybox_fuzzer/src/dictionary.rs +++ b/tooling/greybox_fuzzer/src/dictionary.rs @@ -79,7 +79,7 @@ fn build_dictionary_from_circuit(circuit: &Circuit) -> HashSet< } } if let Some(predicate) = predicate { - insert_expr(&mut constants, predicate) + insert_expr(&mut constants, predicate); } } diff --git a/tooling/greybox_fuzzer/src/lib.rs b/tooling/greybox_fuzzer/src/lib.rs index d2a45d2e1d3..9cf8570285a 100644 --- a/tooling/greybox_fuzzer/src/lib.rs +++ b/tooling/greybox_fuzzer/src/lib.rs @@ -1,3 +1,7 @@ +#![forbid(unsafe_code)] +#![warn(clippy::semicolon_if_nothing_returned)] +#![cfg_attr(not(test), warn(unused_crate_dependencies, unused_extern_crates))] + use core::panic; use std::{ cmp::max, @@ -223,7 +227,7 @@ impl Metrics { pub fn increase_processed_testcase_count(&mut self, update: &usize) { self.processed_testcase_count += update; } - pub fn increment_removed_testcase_count(&mut self) { + fn increment_removed_testcase_count(&mut self) { self.removed_testcase_count += 1; self.removed_testcase_last_round = true; } @@ -770,7 +774,7 @@ impl< .increase_total_brillig_duration_micros(&fast_result.brillig_duration_micros()); self.metrics.increase_total_mutation_time(&fast_result.mutation_time()); if !fast_result.skip_check() { - analysis_queue.push(index) + analysis_queue.push(index); } } diff --git a/tooling/greybox_fuzzer/src/mutation/field.rs b/tooling/greybox_fuzzer/src/mutation/field.rs index 9c019d132b3..0ffc21e6019 100644 --- a/tooling/greybox_fuzzer/src/mutation/field.rs +++ b/tooling/greybox_fuzzer/src/mutation/field.rs @@ -27,6 +27,8 @@ //! There are configurations for determining probability of each top-level and low-level mutation //! Currently, the configurations are constant and "new" methods aren't used, but the architecture is prepared for easier introduction of MOpt (Mutation Optimization) technique in the future +use std::sync::OnceLock; + use super::configurations::{ BASIC_FIELD_ELEMENT_DICTIONARY_UPDATE_CONFIGURATION, BASIC_FIELD_ELEMENT_POW_2_UPDATE_CONFIGURATION, @@ -44,10 +46,25 @@ use rand_xorshift::XorShiftRng; const SMALL_VALUE_MAX: u64 = 0xff; const SMALL_VALUE_MIN: u64 = 1; -static mut POWERS_OF_TWO_INITIALIZED: bool = false; -static mut POWERS_OF_TWO: Vec = Vec::new(); -static mut INVERSE_POWERS_OF_TWO: Vec = Vec::new(); -static mut POWERS_OF_TWO_MINUS_ONE: Vec = Vec::new(); +fn powers_of_two() -> &'static Vec { + static INSTANCE: OnceLock> = OnceLock::new(); + INSTANCE.get_or_init(|| { + (1..=MAX_POW_2) + .map(|i| FieldElement::from(2i128).pow(&FieldElement::from(i))) + .collect::>() + }) +} + +fn powers_of_two_minus_one() -> &'static Vec { + static INSTANCE: OnceLock> = OnceLock::new(); + INSTANCE.get_or_init(|| powers_of_two().iter().map(|x| *x - FieldElement::one()).collect()) +} + +fn inverse_powers_of_two() -> &'static Vec { + static INSTANCE: OnceLock> = OnceLock::new(); + INSTANCE + .get_or_init(|| powers_of_two().iter().map(|p| p.inverse()).collect::>()) +} // We are using bn254 scalar field so 254 is enough const MAX_POW_2: usize = 254; @@ -60,22 +77,6 @@ struct FieldMutator<'a> { impl<'a> FieldMutator<'a> { pub fn new(dictionary: &'a Vec, prng: &'a mut XorShiftRng) -> Self { // Initialize powers of two if we haven't done that yet - unsafe { - if !POWERS_OF_TWO_INITIALIZED { - let powers_of_two = (1..=MAX_POW_2) - .map(|i| FieldElement::from(2i128).pow(&FieldElement::from(i))) - .collect::>(); - INVERSE_POWERS_OF_TWO = - powers_of_two.iter().map(|p| p.inverse()).collect::>(); - - POWERS_OF_TWO_MINUS_ONE = - powers_of_two.iter().map(|x| *x - FieldElement::from(1i128)).collect(); - - POWERS_OF_TWO = powers_of_two; - POWERS_OF_TWO_INITIALIZED = true; - } - }; - assert!(!dictionary.is_empty()); Self { dictionary, prng } } @@ -89,12 +90,12 @@ impl<'a> FieldMutator<'a> { FieldElementSubstitutionMutationOptions::Dictionary => { *self.dictionary.choose(self.prng).unwrap() } - FieldElementSubstitutionMutationOptions::PowerOfTwo => unsafe { - *POWERS_OF_TWO.choose(self.prng).unwrap() - }, - FieldElementSubstitutionMutationOptions::PowerOfTwoMinusOne => unsafe { - *POWERS_OF_TWO_MINUS_ONE.choose(self.prng).unwrap() - }, + FieldElementSubstitutionMutationOptions::PowerOfTwo => { + *powers_of_two().choose(self.prng).unwrap() + } + FieldElementSubstitutionMutationOptions::PowerOfTwoMinusOne => { + *powers_of_two_minus_one().choose(self.prng).unwrap() + } } } @@ -107,9 +108,8 @@ impl<'a> FieldMutator<'a> { #[allow(static_mut_refs)] fn apply_pow_2_update(&mut self, element: FieldElement) -> FieldElement { - let chosen_power_of_two = unsafe { POWERS_OF_TWO.choose(self.prng).unwrap() }; - let chosen_inverse_power_of_two = - unsafe { INVERSE_POWERS_OF_TWO.choose(self.prng).unwrap() }; + let chosen_power_of_two = powers_of_two().choose(self.prng).unwrap(); + let chosen_inverse_power_of_two = inverse_powers_of_two().choose(self.prng).unwrap(); match BASIC_FIELD_ELEMENT_POW_2_UPDATE_CONFIGURATION.select(self.prng) { FieldElementPow2UpdateOptions::Addition => element + *chosen_power_of_two, FieldElementPow2UpdateOptions::Subtraction => element - *chosen_power_of_two, @@ -176,7 +176,7 @@ impl<'a> FieldMutator<'a> { /// * `previous_input` - The input value to mutate, must be a Field variant /// * `dictionary` - A vector of interesting field element values to use in mutations /// * `prng` - Random number generator for selecting mutations -pub fn mutate_field_input_value( +pub(super) fn mutate_field_input_value( previous_input: &InputValue, dictionary: &Vec, prng: &mut XorShiftRng, @@ -209,8 +209,8 @@ mod tests { || result == FieldElement::from(1u32) || result == -FieldElement::from(1u32) || result == FieldElement::from(42u32) - || unsafe { POWERS_OF_TWO.contains(&result) } - || unsafe { POWERS_OF_TWO_MINUS_ONE.contains(&result) } + || powers_of_two().contains(&result) + || powers_of_two_minus_one().contains(&result) ); } @@ -241,14 +241,12 @@ mod tests { // Verify result is different from input assert_ne!(result, element); // Result should be element combined with a power of 2 via +,-,*,/ - assert!(unsafe { - POWERS_OF_TWO.iter().any(|p| { - result == element + *p - || result == element - *p - || result == element * *p - || result == element * p.inverse() - }) - }); + assert!(powers_of_two().iter().any(|p| { + result == element + *p + || result == element - *p + || result == element * *p + || result == element * p.inverse() + })); } } diff --git a/tooling/ssa_fuzzer/Cargo.toml b/tooling/ssa_fuzzer/Cargo.toml index fab3d5bc7da..3129cc44af6 100644 --- a/tooling/ssa_fuzzer/Cargo.toml +++ b/tooling/ssa_fuzzer/Cargo.toml @@ -20,32 +20,14 @@ noirc_driver.workspace = true noirc_abi.workspace = true acvm.workspace = true bn254_blackbox_solver.workspace = true -fxhash.workspace = true -iter-extended.workspace = true -thiserror.workspace = true -num-bigint = "0.4" im.workspace = true -serde.workspace = true -serde_json.workspace = true -serde_with = "3.2.0" -tracing.workspace = true -chrono = "0.4.37" -rayon.workspace = true -cfg-if.workspace = true +thiserror.workspace = true nargo = { path = "../nargo", features = ["rpc"] } -smallvec = { version = "1.13.2", features = ["serde"] } libfuzzer-sys = { version = "0.4.0", features = ["arbitrary-derive"] } -vec-collections = "0.4.3" -env_logger = "0.11.6" log = "0.4" -rand = "0.8" [dev-dependencies] -proptest.workspace = true -similar-asserts.workspace = true -tracing-test = "0.2.5" -num-traits.workspace = true -test-case.workspace = true +rand.workspace = true [features] bn254 = ["noirc_frontend/bn254"] diff --git a/tooling/ssa_fuzzer/src/lib.rs b/tooling/ssa_fuzzer/src/lib.rs index 1ab4c7a05c8..7024a23d161 100644 --- a/tooling/ssa_fuzzer/src/lib.rs +++ b/tooling/ssa_fuzzer/src/lib.rs @@ -1,4 +1,8 @@ -#![allow(dead_code)] +#![forbid(unsafe_code)] +#![warn(unreachable_pub)] +#![warn(clippy::semicolon_if_nothing_returned)] +#![cfg_attr(not(test), warn(unused_crate_dependencies, unused_extern_crates))] + pub mod builder; pub mod compiler; pub mod config;