From b3117459d686b9bbeb52864715a6d2404ba576ae Mon Sep 17 00:00:00 2001 From: Venkkatesh Sekar Date: Fri, 30 Jan 2026 12:42:12 +0000 Subject: [PATCH] init --- Cargo.lock | 10 --- Cargo.toml | 1 - README.md | 6 +- canfuzz/Cargo.toml | 5 -- canfuzz/src/lib.rs | 36 +++++----- canfuzz_derive/Cargo.toml | 15 ----- canfuzz_derive/src/lib.rs | 67 ------------------- .../decode_candid_by_instructions/Cargo.toml | 2 +- .../src/decode_candid_by_instructions.rs | 9 ++- examples/motoko_diff/Cargo.toml | 2 +- examples/motoko_diff/src/motoko_diff.rs | 9 ++- examples/motoko_shim/Cargo.toml | 2 +- examples/motoko_shim/src/motoko_shim.rs | 9 ++- examples/stable_memory_ops/Cargo.toml | 2 +- .../src/stable_memory_ops.rs | 8 +-- examples/trap_after_await/Cargo.toml | 2 +- .../trap_after_await/src/trap_after_await.rs | 8 +-- 17 files changed, 45 insertions(+), 148 deletions(-) delete mode 100644 canfuzz_derive/Cargo.toml delete mode 100644 canfuzz_derive/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 804225f..fc09801 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -354,7 +354,6 @@ dependencies = [ "assert_matches", "candid", "candid_parser", - "canfuzz_derive", "chrono", "difference", "ic-management-canister-types", @@ -373,15 +372,6 @@ dependencies = [ "wirm", ] -[[package]] -name = "canfuzz_derive" -version = "0.5.0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.114", -] - [[package]] name = "cc" version = "1.2.52" diff --git a/Cargo.toml b/Cargo.toml index 8253ec1..acd3e2c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,6 @@ members = [ "build_canister", "canfuzz", - "canfuzz_derive", "canisters/rust/decode_candid", "canisters/rust/ledger", "canisters/rust/stable_memory", diff --git a/README.md b/README.md index 1107f5f..4d93435 100644 --- a/README.md +++ b/README.md @@ -15,10 +15,8 @@ use canfuzz::libafl::executors::ExitKind; use canfuzz::libafl::inputs::BytesInput; use candid::Principal; -// 1. Define a struct for the fuzzer state and derive FuzzerState -// Requires features = ["derive"] in Cargo.toml -#[derive(canfuzz::FuzzerState)] -struct MyFuzzer(FuzzerState); +// 1. Define a struct for the fuzzer state using the macro +canfuzz::define_fuzzer_state!(MyFuzzer); // 2. Implement the core fuzzing logic impl FuzzerOrchestrator for MyFuzzer { diff --git a/canfuzz/Cargo.toml b/canfuzz/Cargo.toml index d4b1086..95ef2e0 100644 --- a/canfuzz/Cargo.toml +++ b/canfuzz/Cargo.toml @@ -30,11 +30,6 @@ wirm = { workspace = true } num-traits = { workspace = true } num-bigint = { workspace = true } naughty-strings = { workspace = true } -canfuzz_derive = { path = "../canfuzz_derive", optional = true } - -[features] -default = [] -derive = ["dep:canfuzz_derive"] [dev-dependencies] wat = { workspace = true } diff --git a/canfuzz/src/lib.rs b/canfuzz/src/lib.rs index 5fa2c43..330e924 100644 --- a/canfuzz/src/lib.rs +++ b/canfuzz/src/lib.rs @@ -17,20 +17,8 @@ //! use canfuzz::libafl::inputs::BytesInput; //! use std::path::PathBuf; //! -//! // 1. Define a struct for your fuzzer and derive FuzzerState. -//! // Note: Requires the "derive" feature enabled for canfuzz. -//! #[cfg_attr(feature = "derive", derive(canfuzz::FuzzerState))] -//! struct MyFuzzer(FuzzerState); -//! -//! // Manual implementation if "derive" feature is not used: -//! #[cfg(not(feature = "derive"))] -//! impl AsRef for MyFuzzer { -//! fn as_ref(&self) -> &FuzzerState { &self.0 } -//! } -//! #[cfg(not(feature = "derive"))] -//! impl AsMut for MyFuzzer { -//! fn as_mut(&mut self) -> &mut FuzzerState { &mut self.0 } -//! } +//! // 1. Define a struct for your fuzzer using the macro. +//! canfuzz::define_fuzzer_state!(MyFuzzer); //! //! // 2. Implement the fuzzing logic. //! impl FuzzerOrchestrator for MyFuzzer { @@ -82,5 +70,21 @@ pub mod custom; pub use libafl; pub use libafl_bolts; -#[cfg(feature = "derive")] -pub use canfuzz_derive::FuzzerState; +#[macro_export] +macro_rules! define_fuzzer_state { + ($name:ident) => { + pub struct $name(pub canfuzz::fuzzer::FuzzerState); + + impl AsRef for $name { + fn as_ref(&self) -> &canfuzz::fuzzer::FuzzerState { + &self.0 + } + } + + impl AsMut for $name { + fn as_mut(&mut self) -> &mut canfuzz::fuzzer::FuzzerState { + &mut self.0 + } + } + }; +} diff --git a/canfuzz_derive/Cargo.toml b/canfuzz_derive/Cargo.toml deleted file mode 100644 index 2270aee..0000000 --- a/canfuzz_derive/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "canfuzz_derive" -version.workspace = true -edition.workspace = true -authors.workspace = true -license.workspace = true -publish = false - -[lib] -proc-macro = true - -[dependencies] -quote = { workspace = true } -syn = { workspace = true } -proc-macro2 = { workspace = true } diff --git a/canfuzz_derive/src/lib.rs b/canfuzz_derive/src/lib.rs deleted file mode 100644 index e29d040..0000000 --- a/canfuzz_derive/src/lib.rs +++ /dev/null @@ -1,67 +0,0 @@ -use proc_macro::TokenStream; -use quote::quote; -use syn::{Data, DeriveInput, Fields, parse_macro_input}; - -#[proc_macro_derive(FuzzerState)] -pub fn derive_fuzzer_state(input: TokenStream) -> TokenStream { - let input = parse_macro_input!(input as DeriveInput); - let name = input.ident; - - let fields = match input.data { - Data::Struct(ref data) => &data.fields, - _ => { - return syn::Error::new_spanned(name, "FuzzerState can only be derived for structs") - .to_compile_error() - .into(); - } - }; - - let field_access = match fields { - Fields::Unnamed(fields) => { - if fields.unnamed.len() == 1 { - quote! { 0 } - } else { - return syn::Error::new_spanned(name, "FuzzerState derive currently only supports newtype structs (tuple structs with one field)").to_compile_error().into(); - } - } - Fields::Named(fields) => { - let state_field = fields - .named - .iter() - .find(|f| f.ident.as_ref().map(|id| id == "state").unwrap_or(false)); - - if let Some(f) = state_field { - let id = &f.ident; - quote! { #id } - } else { - return syn::Error::new_spanned( - name, - "FuzzerState derive on named structs requires a field named 'state'", - ) - .to_compile_error() - .into(); - } - } - Fields::Unit => { - return syn::Error::new_spanned(name, "FuzzerState cannot be derived for unit structs") - .to_compile_error() - .into(); - } - }; - - let expanded = quote! { - impl AsRef for #name { - fn as_ref(&self) -> &canfuzz::fuzzer::FuzzerState { - &self.#field_access - } - } - - impl AsMut for #name { - fn as_mut(&mut self) -> &mut canfuzz::fuzzer::FuzzerState { - &mut self.#field_access - } - } - }; - - TokenStream::from(expanded) -} diff --git a/examples/decode_candid_by_instructions/Cargo.toml b/examples/decode_candid_by_instructions/Cargo.toml index b789223..e490772 100644 --- a/examples/decode_candid_by_instructions/Cargo.toml +++ b/examples/decode_candid_by_instructions/Cargo.toml @@ -14,7 +14,7 @@ path = "src/decode_candid_by_instructions.rs" [dependencies] candid = { workspace = true } -canfuzz = { path = "../../canfuzz/", features = ["derive"] } +canfuzz = { path = "../../canfuzz/" } once_cell = { workspace = true } pocket-ic = { workspace = true } serde = { workspace = true } diff --git a/examples/decode_candid_by_instructions/src/decode_candid_by_instructions.rs b/examples/decode_candid_by_instructions/src/decode_candid_by_instructions.rs index 62769fa..349a0fa 100644 --- a/examples/decode_candid_by_instructions/src/decode_candid_by_instructions.rs +++ b/examples/decode_candid_by_instructions/src/decode_candid_by_instructions.rs @@ -1,7 +1,7 @@ -use canfuzz::FuzzerState; use canfuzz::custom::feedback::oom_exit_kind::OomLogic; use canfuzz::custom::observer::decode_map::{DECODING_MAP_OBSERVER_NAME, DecodingMapFeedback, MAP}; -use canfuzz::fuzzer::{CanisterBuilder, FuzzerBuilder, FuzzerState}; +use canfuzz::define_fuzzer_state; +use canfuzz::fuzzer::{CanisterBuilder, FuzzerBuilder}; use canfuzz::instrumentation::{InstrumentationArgs, Seed, instrument_wasm_for_fuzzing}; use canfuzz::orchestrator::FuzzerOrchestrator; use canfuzz::util::{parse_canister_result_for_trap, read_canister_bytes}; @@ -39,6 +39,8 @@ use canfuzz::libafl::monitors::SimpleMonitor; // use libafl::monitors::tui::{ui::TuiUI, TuiMonitor}; use canfuzz::libafl_bolts::{current_nanos, rands::StdRand, tuples::tuple_list}; +define_fuzzer_state!(DecodeCandidFuzzer); + fn main() { let canister = CanisterBuilder::new("decode_candid") .with_wasm_env("DECODE_CANDID_WASM_PATH") @@ -55,9 +57,6 @@ fn main() { fuzzer_state.run(); } -#[derive(FuzzerState)] -struct DecodeCandidFuzzer(FuzzerState); - impl FuzzerOrchestrator for DecodeCandidFuzzer { fn corpus_dir(&self) -> std::path::PathBuf { PathBuf::from(file!()) diff --git a/examples/motoko_diff/Cargo.toml b/examples/motoko_diff/Cargo.toml index 3bfd86b..55c34bf 100644 --- a/examples/motoko_diff/Cargo.toml +++ b/examples/motoko_diff/Cargo.toml @@ -14,7 +14,7 @@ path = "src/motoko_diff.rs" [dependencies] candid = { workspace = true } -canfuzz = { path = "../../canfuzz/", features = ["derive"] } +canfuzz = { path = "../../canfuzz/" } k256 = { workspace = true } pocket-ic = { workspace = true } sha2 = { workspace = true } diff --git a/examples/motoko_diff/src/motoko_diff.rs b/examples/motoko_diff/src/motoko_diff.rs index 859968c..b877b0d 100644 --- a/examples/motoko_diff/src/motoko_diff.rs +++ b/examples/motoko_diff/src/motoko_diff.rs @@ -1,4 +1,5 @@ use candid::{Decode, Encode, Principal}; +use canfuzz::define_fuzzer_state; use canfuzz::libafl::executors::ExitKind; use canfuzz::libafl::inputs::ValueInput; use k256::U256; @@ -14,12 +15,13 @@ use std::time::Duration; use slog::Level; -use canfuzz::FuzzerState; -use canfuzz::fuzzer::{CanisterBuilder, FuzzerBuilder, FuzzerState}; +use canfuzz::fuzzer::{CanisterBuilder, FuzzerBuilder}; use canfuzz::instrumentation::{InstrumentationArgs, Seed, instrument_wasm_for_fuzzing}; use canfuzz::orchestrator::FuzzerOrchestrator; use canfuzz::util::{parse_canister_result_for_trap, read_canister_bytes}; +define_fuzzer_state!(MotokoDiffFuzzer); + fn main() { let canister = CanisterBuilder::new("ecdsa_sign") .with_wasm_env("MOTOKO_CANISTER_WASM_PATH") @@ -35,9 +37,6 @@ fn main() { fuzzer_state.run(); } -#[derive(FuzzerState)] -struct MotokoDiffFuzzer(FuzzerState); - impl FuzzerOrchestrator for MotokoDiffFuzzer { fn corpus_dir(&self) -> std::path::PathBuf { PathBuf::from(file!()) diff --git a/examples/motoko_shim/Cargo.toml b/examples/motoko_shim/Cargo.toml index ea17673..567304e 100644 --- a/examples/motoko_shim/Cargo.toml +++ b/examples/motoko_shim/Cargo.toml @@ -14,7 +14,7 @@ path = "src/motoko_shim.rs" [dependencies] candid = { workspace = true } -canfuzz = { path = "../../canfuzz/", features = ["derive"] } +canfuzz = { path = "../../canfuzz/" } pocket-ic = { workspace = true } slog = { workspace = true } diff --git a/examples/motoko_shim/src/motoko_shim.rs b/examples/motoko_shim/src/motoko_shim.rs index 66e0721..d174695 100644 --- a/examples/motoko_shim/src/motoko_shim.rs +++ b/examples/motoko_shim/src/motoko_shim.rs @@ -1,4 +1,5 @@ use candid::{Encode, Principal}; +use canfuzz::define_fuzzer_state; use canfuzz::libafl::executors::ExitKind; use canfuzz::libafl::inputs::ValueInput; use pocket_ic::PocketIcBuilder; @@ -7,12 +8,13 @@ use std::time::Duration; use slog::Level; -use canfuzz::FuzzerState; -use canfuzz::fuzzer::{CanisterBuilder, FuzzerBuilder, FuzzerState}; +use canfuzz::fuzzer::{CanisterBuilder, FuzzerBuilder}; use canfuzz::instrumentation::{InstrumentationArgs, Seed, instrument_wasm_for_fuzzing}; use canfuzz::orchestrator::FuzzerOrchestrator; use canfuzz::util::{parse_canister_result_for_trap, read_canister_bytes}; +define_fuzzer_state!(MotokoShimFuzzer); + fn main() { let canister = CanisterBuilder::new("json_decode") .with_wasm_env("MOTOKO_CANISTER_WASM_PATH") @@ -28,9 +30,6 @@ fn main() { fuzzer_state.run(); } -#[derive(FuzzerState)] -struct MotokoShimFuzzer(FuzzerState); - impl FuzzerOrchestrator for MotokoShimFuzzer { fn corpus_dir(&self) -> std::path::PathBuf { PathBuf::from(file!()) diff --git a/examples/stable_memory_ops/Cargo.toml b/examples/stable_memory_ops/Cargo.toml index e0dde42..a6fa3ee 100644 --- a/examples/stable_memory_ops/Cargo.toml +++ b/examples/stable_memory_ops/Cargo.toml @@ -14,7 +14,7 @@ path = "src/stable_memory_ops.rs" [dependencies] candid = { workspace = true } -canfuzz = { path = "../../canfuzz/", features = ["derive"] } +canfuzz = { path = "../../canfuzz/" } once_cell = { workspace = true } pocket-ic = { workspace = true } slog = { workspace = true } diff --git a/examples/stable_memory_ops/src/stable_memory_ops.rs b/examples/stable_memory_ops/src/stable_memory_ops.rs index 7730d1b..54e5a12 100644 --- a/examples/stable_memory_ops/src/stable_memory_ops.rs +++ b/examples/stable_memory_ops/src/stable_memory_ops.rs @@ -1,5 +1,6 @@ use candid::Principal; use canfuzz::custom::mutator::candid::CandidTypeDefArgs; +use canfuzz::define_fuzzer_state; use canfuzz::libafl::executors::ExitKind; use canfuzz::libafl::inputs::ValueInput; use once_cell::sync::OnceCell; @@ -8,13 +9,13 @@ use std::path::PathBuf; use slog::Level; -use canfuzz::FuzzerState; -use canfuzz::fuzzer::{CanisterBuilder, FuzzerBuilder, FuzzerState}; +use canfuzz::fuzzer::{CanisterBuilder, FuzzerBuilder}; use canfuzz::instrumentation::{InstrumentationArgs, Seed, instrument_wasm_for_fuzzing}; use canfuzz::orchestrator::FuzzerOrchestrator; use canfuzz::util::{parse_canister_result_for_trap, read_canister_bytes}; static SNAPSHOT_ID: OnceCell> = OnceCell::new(); +define_fuzzer_state!(StableMemoryFuzzer); fn main() { let canister = CanisterBuilder::new("stable_memory") @@ -32,9 +33,6 @@ fn main() { fuzzer_state.run(); } -#[derive(FuzzerState)] -struct StableMemoryFuzzer(FuzzerState); - impl FuzzerOrchestrator for StableMemoryFuzzer { fn get_candid_args() -> Option { Some(CandidTypeDefArgs { diff --git a/examples/trap_after_await/Cargo.toml b/examples/trap_after_await/Cargo.toml index e72b496..bae4922 100644 --- a/examples/trap_after_await/Cargo.toml +++ b/examples/trap_after_await/Cargo.toml @@ -14,7 +14,7 @@ path = "src/trap_after_await.rs" [dependencies] candid = { workspace = true } -canfuzz = { path = "../../canfuzz/", features = ["derive"] } +canfuzz = { path = "../../canfuzz/" } once_cell = { workspace = true } pocket-ic = { workspace = true } serde = { workspace = true } diff --git a/examples/trap_after_await/src/trap_after_await.rs b/examples/trap_after_await/src/trap_after_await.rs index e0a3796..2033deb 100644 --- a/examples/trap_after_await/src/trap_after_await.rs +++ b/examples/trap_after_await/src/trap_after_await.rs @@ -2,15 +2,15 @@ use std::path::PathBuf; use std::time::Duration; use candid::{Decode, Encode, Principal}; +use canfuzz::define_fuzzer_state; use canfuzz::libafl::executors::ExitKind; use canfuzz::libafl::inputs::ValueInput; use once_cell::sync::OnceCell; use pocket_ic::PocketIcBuilder; use slog::Level; -use canfuzz::FuzzerState; use canfuzz::custom::mutator::candid::CandidTypeDefArgs; -use canfuzz::fuzzer::{CanisterBuilder, FuzzerBuilder, FuzzerState}; +use canfuzz::fuzzer::{CanisterBuilder, FuzzerBuilder}; use canfuzz::instrumentation::{InstrumentationArgs, Seed, instrument_wasm_for_fuzzing}; use canfuzz::orchestrator::FuzzerOrchestrator; @@ -18,6 +18,7 @@ use canfuzz::util::read_canister_bytes; const SYNCHRONOUS_EXECUTION: bool = false; static SNAPSHOT: OnceCell<(Vec, Vec)> = OnceCell::new(); +define_fuzzer_state!(TrapAfterAwaitFuzzer); fn main() { let ledger = CanisterBuilder::new("ledger") @@ -41,9 +42,6 @@ fn main() { fuzzer_state.run(); } -#[derive(FuzzerState)] -struct TrapAfterAwaitFuzzer(FuzzerState); - impl FuzzerOrchestrator for TrapAfterAwaitFuzzer { fn get_candid_args() -> Option { Some(CandidTypeDefArgs {