From 6e57938871330ac50d669090142279cd2998c4a9 Mon Sep 17 00:00:00 2001 From: Guy Repta <50716988+gtrepta@users.noreply.github.com> Date: Thu, 7 May 2026 13:56:23 -0500 Subject: [PATCH 1/7] wip: Implement fuzzing loop --- .../fuzz/fuzz_targets/fuzz_target_1.rs | 92 +++++++++++++++++-- 1 file changed, 82 insertions(+), 10 deletions(-) diff --git a/skribe-fuzz-rs/fuzz/fuzz_targets/fuzz_target_1.rs b/skribe-fuzz-rs/fuzz/fuzz_targets/fuzz_target_1.rs index 9310cf3..e6ddc0b 100644 --- a/skribe-fuzz-rs/fuzz/fuzz_targets/fuzz_target_1.rs +++ b/skribe-fuzz-rs/fuzz/fuzz_targets/fuzz_target_1.rs @@ -1,28 +1,100 @@ #![no_main] +use std::{cell::Cell, sync::OnceLock}; use libfuzzer_sys::fuzz_target; use pico_args::Arguments; -use skribe_fuzz_rs::{kllvm, fuzz_specs_from_json, make_dv}; +use skribe_fuzz_rs::{ + Signature, fuzz_specs_from_json, + kllvm::{self, MarshalError, Marshaller, VarHandler}, + kore, +}; + +struct FuzzConfig { + template: kore::Pattern, + signatures: Vec, + contract_name: String, + function_name: String, +} + +// TODO +struct SignatureFuzzer; + +impl VarHandler for SignatureFuzzer { + fn substitute( + &mut self, + name: &str, + _sort: &kore::Sort, + ) -> Result { + let sort = kore::Sort::App { + id: kore::Id::new("SortBytes".to_string()).unwrap(), + args: vec![], + }; + match name { + "VarCALLDATA" => Ok(kore::Pattern::Dv { + sort, + // TODO + value: "00".into(), + }), + _ => Err(MarshalError::Unsupported( + "Encountered a variable that isn't CALLDATA", + )), + } + } +} + +static FUZZ_CONFIG: OnceLock = OnceLock::new(); fuzz_target!( init: { kllvm::init(); let mut args = Arguments::from_env(); - let fuzz_spec_file: Option = args + let fuzz_spec_file: String = args // You must pass this option as `--fuzz-spec=` with the // equals sign, otherwise libfuzzer treats it as a positional argument - .opt_value_from_str("--fuzz-spec") + .value_from_str("--fuzz-spec") .unwrap(); - if let Some(file) = fuzz_spec_file { - let contents = std::fs::read_to_string(file).unwrap(); - let specs = fuzz_specs_from_json(&contents).unwrap(); - println!("{:?}", specs); - } + let contract_name: String = args + .value_from_str("--contract-name") + .unwrap(); + + let function_name: String = args + .value_from_str("--function-name") + .unwrap(); + + let contents = std::fs::read_to_string(fuzz_spec_file).unwrap(); + let mut specs = fuzz_specs_from_json(&contents).unwrap(); + + // Assuming only one spec came from the json + let spec = specs.remove(0); + + let mut parser = kore::Parser::new(&spec.template).unwrap(); + let template = parser.pattern().unwrap(); + + FUZZ_CONFIG.get_or_init(|| FuzzConfig { template, signatures: spec.signatures, contract_name, function_name }); }, |data: &[u8]| { - let _ = make_dv(); - // fuzzed code goes here + thread_local! { + static MARSHALLER: Cell>> = Cell::new(Some(Marshaller::new(None))) + } + let mut marshaller_cell: Option> = MARSHALLER.take(); + let marshaller = marshaller_cell.as_mut().unwrap(); + + let config = FUZZ_CONFIG.get().unwrap(); + + let sig = SignatureFuzzer{}; + marshaller.set_handler(sig); + + let template = &config.template; + + let kllvm_pattern: kllvm::Pattern = marshaller.marshal(template).unwrap(); + + let mut block: kllvm::Block = kllvm_pattern.into(); + block.take_steps(-1); + + let result: kllvm::Pattern = block.into(); + + MARSHALLER.replace(marshaller_cell); }); From ca9e43374fa70d4de8f8484e2d0e42b473da0427 Mon Sep 17 00:00:00 2001 From: Guy Repta <50716988+gtrepta@users.noreply.github.com> Date: Thu, 7 May 2026 22:15:41 -0500 Subject: [PATCH 2/7] feat: Finish main fuzz loop TODO: ABI parsing/fuzzing/encoding --- .../fuzz/fuzz_targets/fuzz_target_1.rs | 61 ++++++++++++------- 1 file changed, 40 insertions(+), 21 deletions(-) diff --git a/skribe-fuzz-rs/fuzz/fuzz_targets/fuzz_target_1.rs b/skribe-fuzz-rs/fuzz/fuzz_targets/fuzz_target_1.rs index e6ddc0b..e4c7d3c 100644 --- a/skribe-fuzz-rs/fuzz/fuzz_targets/fuzz_target_1.rs +++ b/skribe-fuzz-rs/fuzz/fuzz_targets/fuzz_target_1.rs @@ -18,7 +18,7 @@ struct FuzzConfig { function_name: String, } -// TODO +// TODO: Implement ABI parsing and Arbitrary value generation struct SignatureFuzzer; impl VarHandler for SignatureFuzzer { @@ -34,7 +34,7 @@ impl VarHandler for SignatureFuzzer { match name { "VarCALLDATA" => Ok(kore::Pattern::Dv { sort, - // TODO + // TODO: Implement ABI encoding value: "00".into(), }), _ => Err(MarshalError::Unsupported( @@ -44,57 +44,76 @@ impl VarHandler for SignatureFuzzer { } } -static FUZZ_CONFIG: OnceLock = OnceLock::new(); +// Persistent data across iterations. +// +// FUZZ_CONFIG - The fuzz spec + contract/function names to fuzz. Parsed from the command line +// MARSHALLER - The marshaller for moving terms over to kllvm. Keeps parts of the template +// configuration cached. +thread_local! { + static FUZZ_CONFIG: Cell> = Cell::new(None); + static MARSHALLER: Cell>> = Cell::new(Some(Marshaller::new(None))) +} fuzz_target!( init: { kllvm::init(); - let mut args = Arguments::from_env(); + // Parse arguments + // + // You must pass these options as `--xxx=` with the equals sign, + // otherwise libfuzzer treats `` as a positional argument. + let mut args = Arguments::from_env(); let fuzz_spec_file: String = args - // You must pass this option as `--fuzz-spec=` with the - // equals sign, otherwise libfuzzer treats it as a positional argument .value_from_str("--fuzz-spec") .unwrap(); - let contract_name: String = args .value_from_str("--contract-name") .unwrap(); - let function_name: String = args .value_from_str("--function-name") .unwrap(); + // Parse fuzz spec let contents = std::fs::read_to_string(fuzz_spec_file).unwrap(); let mut specs = fuzz_specs_from_json(&contents).unwrap(); - - // Assuming only one spec came from the json - let spec = specs.remove(0); - + let spec = specs.remove(0); // Assuming only one spec came from the json let mut parser = kore::Parser::new(&spec.template).unwrap(); let template = parser.pattern().unwrap(); - FUZZ_CONFIG.get_or_init(|| FuzzConfig { template, signatures: spec.signatures, contract_name, function_name }); + FUZZ_CONFIG.replace(Some(FuzzConfig { template, signatures: spec.signatures, contract_name, function_name })); }, |data: &[u8]| { - thread_local! { - static MARSHALLER: Cell>> = Cell::new(Some(Marshaller::new(None))) - } let mut marshaller_cell: Option> = MARSHALLER.take(); let marshaller = marshaller_cell.as_mut().unwrap(); + let config_cell = FUZZ_CONFIG.take(); + let config = config_cell.as_ref().unwrap(); - let config = FUZZ_CONFIG.get().unwrap(); - + // Marshal over to kllvm with the CALLDATA variable substituted let sig = SignatureFuzzer{}; marshaller.set_handler(sig); - let template = &config.template; - let kllvm_pattern: kllvm::Pattern = marshaller.marshal(template).unwrap(); + // Execute the semantics let mut block: kllvm::Block = kllvm_pattern.into(); block.take_steps(-1); - let result: kllvm::Pattern = block.into(); + // Check the exit code + let exit_code = get_exit_code(&block); + if exit_code != 0 { + println!("panic!"); + } + FUZZ_CONFIG.replace(config_cell); MARSHALLER.replace(marshaller_cell); }); + +fn get_exit_code(block: &kllvm::Block) -> u32 { + let res_str = format!("{}", block); + let pattern = r#"Lbl'-LT-'exit-code'-GT-'{}(\dv{SortInt{}}(""#; + let idx = res_str.find(pattern).unwrap(); + let slice = &res_str[idx + pattern.len()..]; + let idx2 = slice.find(r#"""#).unwrap(); + let num_str = &slice[..idx2]; + + num_str.parse().unwrap() +} From 100e5106a6350ac731df5e079c67c477d346c877 Mon Sep 17 00:00:00 2001 From: Guy Repta <50716988+gtrepta@users.noreply.github.com> Date: Thu, 7 May 2026 22:35:19 -0500 Subject: [PATCH 3/7] cleanup: Move get_exit_code to libs and remove throwaway code --- .../fuzz/fuzz_targets/fuzz_target_1.rs | 15 ++------- skribe-fuzz-rs/src/lib.rs | 33 ++++++------------- 2 files changed, 12 insertions(+), 36 deletions(-) diff --git a/skribe-fuzz-rs/fuzz/fuzz_targets/fuzz_target_1.rs b/skribe-fuzz-rs/fuzz/fuzz_targets/fuzz_target_1.rs index e4c7d3c..b2d3823 100644 --- a/skribe-fuzz-rs/fuzz/fuzz_targets/fuzz_target_1.rs +++ b/skribe-fuzz-rs/fuzz/fuzz_targets/fuzz_target_1.rs @@ -1,12 +1,12 @@ #![no_main] -use std::{cell::Cell, sync::OnceLock}; +use std::cell::Cell; use libfuzzer_sys::fuzz_target; use pico_args::Arguments; use skribe_fuzz_rs::{ - Signature, fuzz_specs_from_json, + Signature, fuzz_specs_from_json, get_exit_code, kllvm::{self, MarshalError, Marshaller, VarHandler}, kore, }; @@ -106,14 +106,3 @@ fuzz_target!( init: { FUZZ_CONFIG.replace(config_cell); MARSHALLER.replace(marshaller_cell); }); - -fn get_exit_code(block: &kllvm::Block) -> u32 { - let res_str = format!("{}", block); - let pattern = r#"Lbl'-LT-'exit-code'-GT-'{}(\dv{SortInt{}}(""#; - let idx = res_str.find(pattern).unwrap(); - let slice = &res_str[idx + pattern.len()..]; - let idx2 = slice.find(r#"""#).unwrap(); - let num_str = &slice[..idx2]; - - num_str.parse().unwrap() -} diff --git a/skribe-fuzz-rs/src/lib.rs b/skribe-fuzz-rs/src/lib.rs index e3057ab..3ef23fa 100644 --- a/skribe-fuzz-rs/src/lib.rs +++ b/skribe-fuzz-rs/src/lib.rs @@ -7,27 +7,14 @@ pub use fuzz_spec::{FuzzSpec, Signature, fuzz_specs_from_json}; pub use kframework::kore; pub use kframework_ffi::kllvm; -use kframework::kore::{Id, Pattern, Sort}; -use kframework_ffi::kllvm::{Marshaller, VarHandler}; - -struct DummyHandler; - -impl VarHandler for DummyHandler { - fn substitute(&mut self, _name: &str, _sort: &Sort) -> Result { - Err(kllvm::MarshalError::Unsupported("Not handling variables")) - } -} - -pub fn make_dv() -> kllvm::Pattern { - let dv = Pattern::Dv { - sort: Sort::App { - id: Id::new("SortInt".to_string()).unwrap(), - args: vec![], - }, - value: "1".into(), - }; - - let mut marshal: Marshaller = Marshaller::new(None); - - marshal.marshal(&dv).unwrap() +/// Get the cell value from a configuration +pub fn get_exit_code(block: &kllvm::Block) -> u32 { + let res_str = format!("{}", block); + let pattern = r#"Lbl'-LT-'exit-code'-GT-'{}(\dv{SortInt{}}(""#; + let idx = res_str.find(pattern).unwrap(); + let slice = &res_str[idx + pattern.len()..]; + let idx2 = slice.find(r#"""#).unwrap(); + let num_str = &slice[..idx2]; + + num_str.parse().unwrap() } From 4aea1ba796034c94af7f75031156214e28deb2f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20T=C3=B3th?= Date: Fri, 8 May 2026 08:32:06 +0000 Subject: [PATCH 4/7] Update `kframework-rs` dependency version --- skribe-fuzz-rs/Cargo.lock | 4 ++-- skribe-fuzz-rs/Cargo.toml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/skribe-fuzz-rs/Cargo.lock b/skribe-fuzz-rs/Cargo.lock index fffcc0c..fc8c1be 100644 --- a/skribe-fuzz-rs/Cargo.lock +++ b/skribe-fuzz-rs/Cargo.lock @@ -1152,7 +1152,7 @@ dependencies = [ [[package]] name = "kframework" version = "0.1.0" -source = "git+https://github.com/runtimeverification/kframework-rs.git?rev=1e7ee3a#1e7ee3a2377a91090e3c66b21dc2ab49e6bc2373" +source = "git+https://github.com/runtimeverification/kframework-rs.git?rev=73c4986#73c4986cedefa8f2190524fa3f8d0948007cb694" dependencies = [ "clap", "serde", @@ -1162,7 +1162,7 @@ dependencies = [ [[package]] name = "kframework_ffi" version = "0.1.0" -source = "git+https://github.com/runtimeverification/kframework-rs.git?rev=1e7ee3a#1e7ee3a2377a91090e3c66b21dc2ab49e6bc2373" +source = "git+https://github.com/runtimeverification/kframework-rs.git?rev=73c4986#73c4986cedefa8f2190524fa3f8d0948007cb694" dependencies = [ "bindgen", "kframework", diff --git a/skribe-fuzz-rs/Cargo.toml b/skribe-fuzz-rs/Cargo.toml index fca6db0..fb2d2d3 100644 --- a/skribe-fuzz-rs/Cargo.toml +++ b/skribe-fuzz-rs/Cargo.toml @@ -11,8 +11,8 @@ alloy-dyn-abi = "1.5.7" alloy-json-abi = "1.5.7" alloy-primitives = "1.5.7" hex-literal = "1.1.0" -kframework = { git = "https://github.com/runtimeverification/kframework-rs.git", rev = "1e7ee3a" } -kframework_ffi = { git = "https://github.com/runtimeverification/kframework-rs.git", rev = "1e7ee3a" } +kframework = { git = "https://github.com/runtimeverification/kframework-rs.git", rev = "73c4986" } +kframework_ffi = { git = "https://github.com/runtimeverification/kframework-rs.git", rev = "73c4986" } libfuzzer-sys = "0.4" pico-args = "0.5.0" serde = "1.0.228" From 2798c16307d4caa093fbf6d961719b02183e79bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20T=C3=B3th?= Date: Fri, 8 May 2026 10:25:15 +0000 Subject: [PATCH 5/7] Implement `SignatureAbi::arbitrary_input` --- skribe-fuzz-rs/Cargo.lock | 32 ++++++++++++++++++++++++++++++++ skribe-fuzz-rs/Cargo.toml | 4 +++- skribe-fuzz-rs/src/abi.rs | 30 ++++++++++++++++++++++++++---- 3 files changed, 61 insertions(+), 5 deletions(-) diff --git a/skribe-fuzz-rs/Cargo.lock b/skribe-fuzz-rs/Cargo.lock index fc8c1be..c11bd0d 100644 --- a/skribe-fuzz-rs/Cargo.lock +++ b/skribe-fuzz-rs/Cargo.lock @@ -21,7 +21,9 @@ dependencies = [ "alloy-primitives", "alloy-sol-type-parser", "alloy-sol-types", + "arbitrary", "itoa", + "proptest", "serde", "serde_json", "winnow 0.7.15", @@ -46,6 +48,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3b431b4e72cd8bd0ec7a50b4be18e73dab74de0dba180eef171055e5d5926e" dependencies = [ "alloy-rlp", + "arbitrary", "bytes", "cfg-if", "const-hex", @@ -58,6 +61,7 @@ dependencies = [ "keccak-asm", "paste", "proptest", + "proptest-derive", "rand 0.9.4", "rapidhash", "ruint", @@ -207,6 +211,9 @@ name = "arbitrary" version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" +dependencies = [ + "derive_arbitrary", +] [[package]] name = "ark-ff" @@ -705,6 +712,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "derive_more" version = "2.1.1" @@ -1071,6 +1089,7 @@ version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ + "arbitrary", "equivalent", "hashbrown 0.17.0", "serde", @@ -1457,6 +1476,17 @@ dependencies = [ "unarray", ] +[[package]] +name = "proptest-derive" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb6dc647500e84a25a85b100e76c85b8ace114c209432dc174f20aac11d4ed6c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -1625,6 +1655,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0298da754d1395046b0afdc2f20ee76d29a8ae310cd30ffa84ed42acba9cb12a" dependencies = [ "alloy-rlp", + "arbitrary", "ark-ff 0.3.0", "ark-ff 0.4.2", "ark-ff 0.5.0", @@ -1848,6 +1879,7 @@ dependencies = [ "alloy-dyn-abi", "alloy-json-abi", "alloy-primitives", + "arbitrary", "hex-literal", "kframework", "kframework_ffi", diff --git a/skribe-fuzz-rs/Cargo.toml b/skribe-fuzz-rs/Cargo.toml index fb2d2d3..32c9ae4 100644 --- a/skribe-fuzz-rs/Cargo.toml +++ b/skribe-fuzz-rs/Cargo.toml @@ -7,9 +7,10 @@ version = "0.1.0" edition = "2024" [workspace.dependencies] -alloy-dyn-abi = "1.5.7" +alloy-dyn-abi = { version = "1.5.7", features = ["arbitrary"] } alloy-json-abi = "1.5.7" alloy-primitives = "1.5.7" +arbitrary = "1.4.2" hex-literal = "1.1.0" kframework = { git = "https://github.com/runtimeverification/kframework-rs.git", rev = "73c4986" } kframework_ffi = { git = "https://github.com/runtimeverification/kframework-rs.git", rev = "73c4986" } @@ -26,6 +27,7 @@ edition.workspace = true [dependencies] alloy-json-abi.workspace = true alloy-dyn-abi.workspace = true +arbitrary.workspace = true serde.workspace = true serde_json.workspace = true kframework.workspace = true diff --git a/skribe-fuzz-rs/src/abi.rs b/skribe-fuzz-rs/src/abi.rs index 2109ecc..2898163 100644 --- a/skribe-fuzz-rs/src/abi.rs +++ b/skribe-fuzz-rs/src/abi.rs @@ -1,6 +1,7 @@ use crate::Signature; use alloy_dyn_abi::{DynSolType, DynSolValue, JsonAbiExt}; use alloy_json_abi::Function; +use arbitrary::Unstructured; use std::fmt::Debug; #[derive(Debug)] @@ -30,11 +31,18 @@ impl SignatureAbi { Ok(SignatureAbi { types, function }) } - pub fn types(&self) -> &[DynSolType] { - &self.types + pub fn arbitrary_input(&self, u: &mut Unstructured<'_>) -> arbitrary::Result> { + let values = self + .types + .iter() + .map(|ty| DynSolValue::arbitrary_from_type(ty, u)) + .collect::>>()?; + + self.encode_input(&values) + .map_err(|_| arbitrary::Error::IncorrectFormat) } - pub fn encode_input(&self, values: &[DynSolValue]) -> Result, String> { + fn encode_input(&self, values: &[DynSolValue]) -> Result, String> { self.function .abi_encode_input(values) .map_err(|e| e.to_string()) @@ -70,7 +78,7 @@ mod tests { ]; // When - let actual = abi.types(); + let actual = abi.types; // Then assert_eq!(actual, expected); @@ -119,6 +127,20 @@ mod tests { assert_eq!(actual, expected); } + #[test] + fn test_arbitrary_input() { + // Given + let abi = signature_abi(); + let raw = vec![0u8; 256]; + let mut u = Unstructured::new(&raw); + + // When + let result = abi.arbitrary_input(&mut u); + + // Then + assert!(result.is_ok()); + } + fn signature_abi() -> SignatureAbi { SignatureAbi::from_signature(signature()).unwrap() } From 6f0bc7edc62d008d13196ce47b1e1b039c067438 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20T=C3=B3th?= Date: Fri, 8 May 2026 11:08:19 +0000 Subject: [PATCH 6/7] Generate random calldata in the fuzzer --- skribe-fuzz-rs/Cargo.lock | 1 + skribe-fuzz-rs/fuzz/Cargo.toml | 1 + .../fuzz/fuzz_targets/fuzz_target_1.rs | 46 ++++++++++++------- 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/skribe-fuzz-rs/Cargo.lock b/skribe-fuzz-rs/Cargo.lock index c11bd0d..42097c1 100644 --- a/skribe-fuzz-rs/Cargo.lock +++ b/skribe-fuzz-rs/Cargo.lock @@ -1891,6 +1891,7 @@ dependencies = [ name = "skribe-libfuzzer" version = "0.0.0" dependencies = [ + "arbitrary", "libfuzzer-sys", "pico-args", "skribe-fuzz-rs", diff --git a/skribe-fuzz-rs/fuzz/Cargo.toml b/skribe-fuzz-rs/fuzz/Cargo.toml index 48bffaa..570d5b1 100644 --- a/skribe-fuzz-rs/fuzz/Cargo.toml +++ b/skribe-fuzz-rs/fuzz/Cargo.toml @@ -8,6 +8,7 @@ edition.workspace = true cargo-fuzz = true [dependencies] +arbitrary.workspace = true libfuzzer-sys.workspace = true pico-args = { workspace = true, features = ["eq-separator"] } diff --git a/skribe-fuzz-rs/fuzz/fuzz_targets/fuzz_target_1.rs b/skribe-fuzz-rs/fuzz/fuzz_targets/fuzz_target_1.rs index b2d3823..32504db 100644 --- a/skribe-fuzz-rs/fuzz/fuzz_targets/fuzz_target_1.rs +++ b/skribe-fuzz-rs/fuzz/fuzz_targets/fuzz_target_1.rs @@ -1,25 +1,23 @@ #![no_main] use std::cell::Cell; +use arbitrary::Unstructured; use libfuzzer_sys::fuzz_target; use pico_args::Arguments; use skribe_fuzz_rs::{ - Signature, fuzz_specs_from_json, get_exit_code, + FuzzSpec, Signature, SignatureAbi, fuzz_specs_from_json, get_exit_code, kllvm::{self, MarshalError, Marshaller, VarHandler}, kore, }; struct FuzzConfig { template: kore::Pattern, - signatures: Vec, - contract_name: String, - function_name: String, + abi: SignatureAbi, } -// TODO: Implement ABI parsing and Arbitrary value generation -struct SignatureFuzzer; +struct SignatureFuzzer(Vec); impl VarHandler for SignatureFuzzer { fn substitute( @@ -31,12 +29,9 @@ impl VarHandler for SignatureFuzzer { id: kore::Id::new("SortBytes".to_string()).unwrap(), args: vec![], }; + let value = kore::Str(self.0.iter().map(|&b| b as char).collect()); match name { - "VarCALLDATA" => Ok(kore::Pattern::Dv { - sort, - // TODO: Implement ABI encoding - value: "00".into(), - }), + "VarCALLDATA" => Ok(kore::Pattern::Dv { sort, value }), _ => Err(MarshalError::Unsupported( "Encountered a variable that isn't CALLDATA", )), @@ -74,12 +69,15 @@ fuzz_target!( init: { // Parse fuzz spec let contents = std::fs::read_to_string(fuzz_spec_file).unwrap(); - let mut specs = fuzz_specs_from_json(&contents).unwrap(); - let spec = specs.remove(0); // Assuming only one spec came from the json - let mut parser = kore::Parser::new(&spec.template).unwrap(); + let specs = fuzz_specs_from_json(&contents).unwrap(); + let (template_str, signature) = extract_template_and_signature(specs, &contract_name, &function_name).unwrap(); + + let mut parser = kore::Parser::new(&template_str).unwrap(); let template = parser.pattern().unwrap(); - FUZZ_CONFIG.replace(Some(FuzzConfig { template, signatures: spec.signatures, contract_name, function_name })); + let abi = SignatureAbi::from_signature(signature).unwrap(); + + FUZZ_CONFIG.replace(Some(FuzzConfig { template, abi })); }, |data: &[u8]| { let mut marshaller_cell: Option> = MARSHALLER.take(); @@ -88,7 +86,9 @@ fuzz_target!( init: { let config = config_cell.as_ref().unwrap(); // Marshal over to kllvm with the CALLDATA variable substituted - let sig = SignatureFuzzer{}; + let mut u = Unstructured::new(data); + let input = config.abi.arbitrary_input(&mut u).unwrap(); + let sig = SignatureFuzzer(input); marshaller.set_handler(sig); let template = &config.template; let kllvm_pattern: kllvm::Pattern = marshaller.marshal(template).unwrap(); @@ -106,3 +106,17 @@ fuzz_target!( init: { FUZZ_CONFIG.replace(config_cell); MARSHALLER.replace(marshaller_cell); }); + +pub fn extract_template_and_signature( + specs: Vec, + contract_name: &str, + function_name: &str, +) -> Option<(String, Signature)> { + specs.into_iter().find_map(|spec| { + let template = spec.template; + spec.signatures + .into_iter() + .find(|sig| sig.contract_name == contract_name && sig.name == function_name) + .map(|sig| (template.clone(), sig)) + }) +} From 61ff123784a6e8fafc41547b07ebef12f15d830a Mon Sep 17 00:00:00 2001 From: devops Date: Fri, 8 May 2026 03:37:53 +0000 Subject: [PATCH 7/7] Set Version: 0.1.36 --- package/version | 2 +- pyproject.toml | 2 +- uv.lock | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package/version b/package/version index a52e041..072d0fa 100644 --- a/package/version +++ b/package/version @@ -1 +1 @@ -0.1.35 +0.1.36 diff --git a/pyproject.toml b/pyproject.toml index b82ee07..53fcb9c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "skribe" -version = "0.1.35" +version = "0.1.36" description = "Property testing for Stylus smart contracts" readme = "README.md" requires-python = "~=3.10" diff --git a/uv.lock b/uv.lock index 3b5c721..3c53775 100644 --- a/uv.lock +++ b/uv.lock @@ -1815,7 +1815,7 @@ wheels = [ [[package]] name = "skribe" -version = "0.1.35" +version = "0.1.36" source = { editable = "." } dependencies = [ { name = "kontrol" },