From 57eeb9cf93589ee42a8e1b3413f0811bbf942273 Mon Sep 17 00:00:00 2001 From: Guy Repta <50716988+gtrepta@users.noreply.github.com> Date: Wed, 13 May 2026 21:49:55 -0500 Subject: [PATCH 01/10] feat: Add `rust-toolchain.toml` --- skribe-fuzz-rs/rust-toolchain.toml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 skribe-fuzz-rs/rust-toolchain.toml diff --git a/skribe-fuzz-rs/rust-toolchain.toml b/skribe-fuzz-rs/rust-toolchain.toml new file mode 100644 index 0000000..f25b5b1 --- /dev/null +++ b/skribe-fuzz-rs/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "1.95.0" From 3a2367d305f78333f9e5a281ecedba751e4bb071 Mon Sep 17 00:00:00 2001 From: Guy Repta <50716988+gtrepta@users.noreply.github.com> Date: Mon, 11 May 2026 11:18:13 -0500 Subject: [PATCH 02/10] refactoring: Extract module `fuzz_config` --- skribe-fuzz-rs/Cargo.lock | 2 - .../fuzz/fuzz_targets/fuzz_target_1.rs | 46 ++----------------- skribe-fuzz-rs/src/fuzz_config.rs | 31 +++++++++++++ skribe-fuzz-rs/src/fuzz_spec.rs | 14 ++++++ skribe-fuzz-rs/src/lib.rs | 4 +- 5 files changed, 51 insertions(+), 46 deletions(-) create mode 100644 skribe-fuzz-rs/src/fuzz_config.rs diff --git a/skribe-fuzz-rs/Cargo.lock b/skribe-fuzz-rs/Cargo.lock index 42097c1..d43adfe 100644 --- a/skribe-fuzz-rs/Cargo.lock +++ b/skribe-fuzz-rs/Cargo.lock @@ -1171,7 +1171,6 @@ dependencies = [ [[package]] name = "kframework" version = "0.1.0" -source = "git+https://github.com/runtimeverification/kframework-rs.git?rev=73c4986#73c4986cedefa8f2190524fa3f8d0948007cb694" dependencies = [ "clap", "serde", @@ -1181,7 +1180,6 @@ dependencies = [ [[package]] name = "kframework_ffi" version = "0.1.0" -source = "git+https://github.com/runtimeverification/kframework-rs.git?rev=73c4986#73c4986cedefa8f2190524fa3f8d0948007cb694" dependencies = [ "bindgen", "kframework", 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 32504db..2ce94bd 100644 --- a/skribe-fuzz-rs/fuzz/fuzz_targets/fuzz_target_1.rs +++ b/skribe-fuzz-rs/fuzz/fuzz_targets/fuzz_target_1.rs @@ -7,38 +7,12 @@ use libfuzzer_sys::fuzz_target; use pico_args::Arguments; use skribe_fuzz_rs::{ - FuzzSpec, Signature, SignatureAbi, fuzz_specs_from_json, get_exit_code, - kllvm::{self, MarshalError, Marshaller, VarHandler}, + FuzzConfig, FuzzSpec, Signature, SignatureAbi, SignatureFuzzer, extract_template_and_signature, + fuzz_specs_from_json, get_exit_code, + kllvm::{self, Marshaller}, kore, }; -struct FuzzConfig { - template: kore::Pattern, - abi: SignatureAbi, -} - -struct SignatureFuzzer(Vec); - -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![], - }; - let value = kore::Str(self.0.iter().map(|&b| b as char).collect()); - match name { - "VarCALLDATA" => Ok(kore::Pattern::Dv { sort, value }), - _ => Err(MarshalError::Unsupported( - "Encountered a variable that isn't CALLDATA", - )), - } - } -} - // Persistent data across iterations. // // FUZZ_CONFIG - The fuzz spec + contract/function names to fuzz. Parsed from the command line @@ -106,17 +80,3 @@ 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)) - }) -} diff --git a/skribe-fuzz-rs/src/fuzz_config.rs b/skribe-fuzz-rs/src/fuzz_config.rs new file mode 100644 index 0000000..3c3ac48 --- /dev/null +++ b/skribe-fuzz-rs/src/fuzz_config.rs @@ -0,0 +1,31 @@ +use kframework::kore; +use kframework_ffi::kllvm::{MarshalError, VarHandler}; + +use crate::SignatureAbi; + +pub struct FuzzConfig { + pub template: kore::Pattern, + pub abi: SignatureAbi, +} + +pub struct SignatureFuzzer(pub Vec); + +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![], + }; + let value = kore::Str(self.0.iter().map(|&b| b as char).collect()); + match name { + "VarCALLDATA" => Ok(kore::Pattern::Dv { sort, value }), + _ => Err(MarshalError::Unsupported( + "Encountered a variable that isn't CALLDATA", + )), + } + } +} diff --git a/skribe-fuzz-rs/src/fuzz_spec.rs b/skribe-fuzz-rs/src/fuzz_spec.rs index 6eeaa18..8221d3b 100644 --- a/skribe-fuzz-rs/src/fuzz_spec.rs +++ b/skribe-fuzz-rs/src/fuzz_spec.rs @@ -17,6 +17,20 @@ pub fn fuzz_specs_from_json(json: &str) -> Result, serde_json::Err serde_json::from_str(json) } +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)) + }) +} + #[cfg(test)] mod tests { use super::*; diff --git a/skribe-fuzz-rs/src/lib.rs b/skribe-fuzz-rs/src/lib.rs index 3ef23fa..64b169d 100644 --- a/skribe-fuzz-rs/src/lib.rs +++ b/skribe-fuzz-rs/src/lib.rs @@ -1,8 +1,10 @@ mod abi; +mod fuzz_config; mod fuzz_spec; pub use abi::SignatureAbi; -pub use fuzz_spec::{FuzzSpec, Signature, fuzz_specs_from_json}; +pub use fuzz_config::{FuzzConfig, SignatureFuzzer}; +pub use fuzz_spec::{FuzzSpec, Signature, extract_template_and_signature, fuzz_specs_from_json}; pub use kframework::kore; pub use kframework_ffi::kllvm; From 9bd9734866030bf1d7deefa7fba6bed80bd08899 Mon Sep 17 00:00:00 2001 From: Guy Repta <50716988+gtrepta@users.noreply.github.com> Date: Mon, 11 May 2026 13:40:03 -0500 Subject: [PATCH 03/10] feat: Add binary `skribe-fuzz` --- skribe-fuzz-rs/Cargo.toml | 4 ++++ skribe-fuzz-rs/bin/skribe_fuzz.rs | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 skribe-fuzz-rs/bin/skribe_fuzz.rs diff --git a/skribe-fuzz-rs/Cargo.toml b/skribe-fuzz-rs/Cargo.toml index 32c9ae4..4c149e5 100644 --- a/skribe-fuzz-rs/Cargo.toml +++ b/skribe-fuzz-rs/Cargo.toml @@ -32,8 +32,12 @@ serde.workspace = true serde_json.workspace = true kframework.workspace = true kframework_ffi.workspace = true +pico-args = { workspace = true, features = ["eq-separator"] } [dev-dependencies] alloy-primitives.workspace = true hex-literal.workspace = true +[[bin]] +name = "skribe-fuzz" +path = "bin/skribe_fuzz.rs" diff --git a/skribe-fuzz-rs/bin/skribe_fuzz.rs b/skribe-fuzz-rs/bin/skribe_fuzz.rs new file mode 100644 index 0000000..4e29ac3 --- /dev/null +++ b/skribe-fuzz-rs/bin/skribe_fuzz.rs @@ -0,0 +1,25 @@ +use skribe_fuzz_rs::{SignatureAbi, kore, extract_template_and_signature, fuzz_specs_from_json}; +use pico_args::Arguments; + +fn main() { + let mut args = Arguments::from_env(); + let fuzz_spec_file: String = args + .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 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(); + + let abi = SignatureAbi::from_signature(signature).unwrap(); +} From 04067b9756310519134c500a110002b893a70ab3 Mon Sep 17 00:00:00 2001 From: Guy Repta <50716988+gtrepta@users.noreply.github.com> Date: Mon, 11 May 2026 19:50:08 -0500 Subject: [PATCH 04/10] feat: Use LibAFL to fuzz --- skribe-fuzz-rs/Cargo.lock | 835 ++++++++++++++++++++++++++++++ skribe-fuzz-rs/Cargo.toml | 4 + skribe-fuzz-rs/bin/skribe_fuzz.rs | 167 +++++- 3 files changed, 995 insertions(+), 11 deletions(-) diff --git a/skribe-fuzz-rs/Cargo.lock b/skribe-fuzz-rs/Cargo.lock index d43adfe..dac1b0b 100644 --- a/skribe-fuzz-rs/Cargo.lock +++ b/skribe-fuzz-rs/Cargo.lock @@ -2,6 +2,33 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "addr2line" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.4" @@ -215,6 +242,18 @@ dependencies = [ "derive_arbitrary", ] +[[package]] +name = "arbitrary-int" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "825297538d77367557b912770ca3083f778a196054b3ee63b22673c4a3cae0a5" + +[[package]] +name = "arbitrary-int" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "993a810118f8f37e9c4411c86f1c4c940a09a7ab34b7bf2d88d06f50c553fab7" + [[package]] name = "ark-ff" version = "0.3.0" @@ -427,6 +466,21 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "backtrace" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-link", +] + [[package]] name = "base16ct" version = "0.2.0" @@ -439,6 +493,26 @@ version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" +[[package]] +name = "bincode" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740" +dependencies = [ + "bincode_derive", + "serde", + "unty", +] + +[[package]] +name = "bincode_derive" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09" +dependencies = [ + "virtue", +] + [[package]] name = "bindgen" version = "0.72.1" @@ -474,6 +548,18 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" +[[package]] +name = "bitbybit" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec187a89ab07e209270175faf9e07ceb2755d984954e58a2296e325ddece2762" +dependencies = [ + "arbitrary-int 1.3.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "bitflags" version = "2.11.1" @@ -501,12 +587,24 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" + [[package]] name = "byte-slice-cast" version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" +[[package]] +name = "bytemuck" +version = "1.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" + [[package]] name = "byteorder" version = "1.5.0" @@ -549,6 +647,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "clang-sys" version = "1.8.1" @@ -600,6 +704,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" +[[package]] +name = "cobs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +dependencies = [ + "thiserror", +] + [[package]] name = "colorchoice" version = "1.0.5" @@ -645,6 +758,15 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "const_panic" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e262cdaac42494e3ae34c43969f9cdeb7da178bdb4b66fa6a1ea2edb4c8ae652" +dependencies = [ + "typewit", +] + [[package]] name = "convert_case" version = "0.10.0" @@ -691,6 +813,22 @@ dependencies = [ "typenum", ] +[[package]] +name = "ctor" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "424e0138278faeb2b401f174ad17e715c829512d74f3d1e81eb43365c2e0590e" +dependencies = [ + "ctor-proc-macro", + "dtor", +] + +[[package]] +name = "ctor-proc-macro" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1" + [[package]] name = "der" version = "0.7.10" @@ -767,6 +905,21 @@ dependencies = [ "subtle", ] +[[package]] +name = "dtor" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "404d02eeb088a82cfd873006cb713fe411306c7d182c344905e101fb1167d301" +dependencies = [ + "dtor-proc-macro", +] + +[[package]] +name = "dtor-proc-macro" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5" + [[package]] name = "dunce" version = "1.0.5" @@ -824,6 +977,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + [[package]] name = "enum-ordinalize" version = "4.3.2" @@ -850,6 +1015,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "erased-serde" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec" +dependencies = [ + "serde", + "serde_core", + "typeid", +] + [[package]] name = "errno" version = "0.3.14" @@ -860,6 +1036,17 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "fastbloom" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7f34442dbe69c60fe8eaf58a8cafff81a1f278816d8ab4db255b3bef4ac3c4" +dependencies = [ + "getrandom 0.3.4", + "libm", + "siphasher", +] + [[package]] name = "fastrand" version = "2.4.1" @@ -934,12 +1121,46 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "funty" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] + [[package]] name = "generic-array" version = "0.14.9" @@ -987,6 +1208,12 @@ dependencies = [ "wasip3", ] +[[package]] +name = "gimli" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" + [[package]] name = "glob" version = "0.3.3" @@ -1057,6 +1284,17 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "hostname" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617aaa3557aef3810a6369d0a99fac8a080891b68bd9f9812a1eeda0c0730cbd" +dependencies = [ + "cfg-if", + "libc", + "windows-link", +] + [[package]] name = "id-arena" version = "2.3.0" @@ -1136,6 +1374,18 @@ dependencies = [ "libc", ] +[[package]] +name = "js-sys" +version = "0.3.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08" +dependencies = [ + "cfg-if", + "futures-util", + "once_cell", + "wasm-bindgen", +] + [[package]] name = "k256" version = "0.13.4" @@ -1207,6 +1457,93 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" +[[package]] +name = "libafl" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81e13655171e69ad9094dd1be1948950a36d228f01a7cb9f6d8477090d98c6e4" +dependencies = [ + "ahash", + "arbitrary-int 2.1.1", + "backtrace", + "bincode", + "bitbybit", + "const_format", + "const_panic", + "fastbloom", + "fs2", + "hashbrown 0.16.1", + "libafl_bolts", + "libafl_derive", + "libc", + "libm", + "log", + "meminterval", + "nix", + "num-traits", + "postcard", + "regex", + "rustversion", + "serde", + "serde_json", + "serial_test", + "tuple_list", + "typed-builder", + "uuid", + "wait-timeout", + "winapi", + "windows", +] + +[[package]] +name = "libafl_bolts" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52cbae44f69156f035ae2196b135ad27ea95020767e6787bfe45e8c2438c67b9" +dependencies = [ + "ahash", + "backtrace", + "ctor", + "erased-serde", + "hashbrown 0.16.1", + "hostname", + "libafl_derive", + "libc", + "log", + "mach2", + "miniz_oxide", + "nix", + "num_enum", + "once_cell", + "postcard", + "rand_core 0.9.5", + "rustversion", + "serde", + "serial_test", + "static_assertions", + "tuple_list", + "typeid", + "uds", + "uuid", + "wide", + "winapi", + "windows", + "windows-core", + "windows-result", + "xxhash-rust", +] + +[[package]] +name = "libafl_derive" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61adf76899bffdcd15ae7fea42b978e7df7cf9213aacdd8cdcda89e4bb3bc32d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "libc" version = "0.2.186" @@ -1245,12 +1582,30 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + [[package]] name = "log" version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +[[package]] +name = "mach2" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a1b95cd5421ec55b445b5ae102f5ea0e768de1f82bd3001e11f426c269c3aea" +dependencies = [ + "libc", +] + [[package]] name = "macro-string" version = "0.1.4" @@ -1268,12 +1623,53 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +[[package]] +name = "meminterval" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e0f9a537564310a87dc77d5c88a407e27dd0aa740e070f0549439cfcc68fcfd" +dependencies = [ + "num-traits", + "serde", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + [[package]] name = "minimal-lexical" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", +] + +[[package]] +name = "nix" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", + "memoffset", +] + [[package]] name = "nom" version = "7.1.3" @@ -1313,6 +1709,36 @@ dependencies = [ "libm", ] +[[package]] +name = "num_enum" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.21.4" @@ -1353,6 +1779,29 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + [[package]] name = "paste" version = "1.0.15" @@ -1375,6 +1824,12 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + [[package]] name = "pkcs8" version = "0.10.2" @@ -1385,6 +1840,18 @@ dependencies = [ "spki", ] +[[package]] +name = "postcard" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" +dependencies = [ + "cobs", + "embedded-io 0.4.0", + "embedded-io 0.6.1", + "serde", +] + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -1597,6 +2064,15 @@ dependencies = [ "rustversion", ] +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags", +] + [[package]] name = "regex" version = "1.12.3" @@ -1681,6 +2157,12 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" +[[package]] +name = "rustc-demangle" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" + [[package]] name = "rustc-hash" version = "2.1.2" @@ -1742,6 +2224,36 @@ dependencies = [ "wait-timeout", ] +[[package]] +name = "safe_arch" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "scc" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46e6f046b7fef48e2660c57ed794263155d713de679057f2d0c169bfc6e756cc" +dependencies = [ + "sdd", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sdd" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca" + [[package]] name = "sec1" version = "0.7.3" @@ -1823,6 +2335,30 @@ dependencies = [ "zmij", ] +[[package]] +name = "serial_test" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "911bd979bf1070a3f3aa7b691a3b3e9968f339ceeec89e08c280a8a22207a32f" +dependencies = [ + "log", + "once_cell", + "parking_lot", + "scc", + "serial_test_derive", +] + +[[package]] +name = "serial_test_derive" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a7d91949b85b0d2fb687445e448b40d322b6b3e4af6b44a29b21d9a5f33e6d9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "sha2" version = "0.10.9" @@ -1870,6 +2406,12 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "siphasher" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" + [[package]] name = "skribe-fuzz-rs" version = "0.1.0" @@ -1881,6 +2423,9 @@ dependencies = [ "hex-literal", "kframework", "kframework_ffi", + "libafl", + "libafl_bolts", + "pico-args", "serde", "serde_json", ] @@ -1895,6 +2440,18 @@ dependencies = [ "skribe-fuzz-rs", ] +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + [[package]] name = "spki" version = "0.7.3" @@ -1976,6 +2533,26 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "toml_datetime" version = "1.1.1+spec-1.1.0" @@ -2006,18 +2583,65 @@ dependencies = [ "winnow 1.0.2", ] +[[package]] +name = "tuple_list" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "141fb9f71ee586d956d7d6e4d5a9ef8e946061188520140f7591b668841d502e" + +[[package]] +name = "typed-builder" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "398a3a3c918c96de527dc11e6e846cd549d4508030b8a33e1da12789c856b81a" +dependencies = [ + "typed-builder-macro", +] + +[[package]] +name = "typed-builder-macro" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e48cea23f68d1f78eb7bc092881b6bb88d3d6b5b7e6234f6f9c911da1ffb221" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "typeid" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" + [[package]] name = "typenum" version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" +[[package]] +name = "typewit" +version = "1.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "214ca0b2191785cbc06209b9ca1861e048e39b5ba33574b3cedd58363d5bb5f6" + [[package]] name = "ucd-trie" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" +[[package]] +name = "uds" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "885c31f06fce836457fe3ef09a59f83fe8db95d270b11cd78f40a4666c4d1661" +dependencies = [ + "libc", +] + [[package]] name = "uint" version = "0.9.5" @@ -2054,12 +2678,30 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "unty" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" + [[package]] name = "utf8parse" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "uuid" +version = "1.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" +dependencies = [ + "getrandom 0.4.2", + "js-sys", + "serde_core", + "wasm-bindgen", +] + [[package]] name = "valuable" version = "0.1.1" @@ -2072,6 +2714,12 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "virtue" +version = "0.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1" + [[package]] name = "wait-timeout" version = "0.2.1" @@ -2105,6 +2753,51 @@ dependencies = [ "wit-bindgen 0.51.0", ] +[[package]] +name = "wasm-bindgen" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.117", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441" +dependencies = [ + "unicode-ident", +] + [[package]] name = "wasm-encoder" version = "0.244.0" @@ -2139,12 +2832,139 @@ dependencies = [ "semver 1.0.28", ] +[[package]] +name = "wide" +version = "0.7.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce5da8ecb62bcd8ec8b7ea19f69a51275e91299be594ea5cc6ef7819e16cd03" +dependencies = [ + "bytemuck", + "safe_arch", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" +dependencies = [ + "windows-collections", + "windows-core", + "windows-future", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" +dependencies = [ + "windows-core", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core", + "windows-link", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-numerics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" +dependencies = [ + "windows-core", + "windows-link", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-sys" version = "0.61.2" @@ -2154,6 +2974,15 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-threading" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link", +] + [[package]] name = "winnow" version = "0.7.15" @@ -2275,6 +3104,12 @@ dependencies = [ "tap", ] +[[package]] +name = "xxhash-rust" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" + [[package]] name = "zerocopy" version = "0.8.48" diff --git a/skribe-fuzz-rs/Cargo.toml b/skribe-fuzz-rs/Cargo.toml index 4c149e5..4d177cd 100644 --- a/skribe-fuzz-rs/Cargo.toml +++ b/skribe-fuzz-rs/Cargo.toml @@ -14,6 +14,8 @@ 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" } +libafl = "0.15.4" +libafl_bolts = "0.15.4" libfuzzer-sys = "0.4" pico-args = "0.5.0" serde = "1.0.228" @@ -32,6 +34,8 @@ serde.workspace = true serde_json.workspace = true kframework.workspace = true kframework_ffi.workspace = true +libafl.workspace = true +libafl_bolts.workspace = true pico-args = { workspace = true, features = ["eq-separator"] } [dev-dependencies] diff --git a/skribe-fuzz-rs/bin/skribe_fuzz.rs b/skribe-fuzz-rs/bin/skribe_fuzz.rs index 4e29ac3..3a6f12e 100644 --- a/skribe-fuzz-rs/bin/skribe_fuzz.rs +++ b/skribe-fuzz-rs/bin/skribe_fuzz.rs @@ -1,25 +1,170 @@ -use skribe_fuzz_rs::{SignatureAbi, kore, extract_template_and_signature, fuzz_specs_from_json}; +#![allow(static_mut_refs)] + +use arbitrary::Unstructured; use pico_args::Arguments; +use skribe_fuzz_rs::{ + FuzzConfig, SignatureAbi, SignatureFuzzer, extract_template_and_signature, + fuzz_specs_from_json, get_exit_code, + kllvm::{self, Marshaller}, + kore, +}; + +use std::cell::Cell; +use std::path::PathBuf; + +use libafl::{ + Fuzzer, StdFuzzer, + corpus::{InMemoryCorpus, OnDiskCorpus}, + events::SimpleEventManager, + executors::{ExitKind, InProcessExecutor}, + feedbacks::{CrashFeedback, MaxMapFeedback}, + generators::RandPrintablesGenerator, + inputs::BytesInput, + monitors::SimpleMonitor, + mutators::{HavocScheduledMutator, havoc_mutations}, + nonzero, + observers::StdMapObserver, + schedulers::QueueScheduler, + stages::StdMutationalStage, + state::StdState, +}; +use libafl_bolts::{rands::StdRand, tuples::tuple_list}; + +// Byte array for the coverage updates +// TODO: Determine a proper length for this +static mut SIGNALS: [u8; 16] = [0; 16]; + +// 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> = const { Cell::new(None) }; + static MARSHALLER: Cell>> = Cell::new(Some(Marshaller::new(None))) +} fn main() { + kllvm::init(); + + // Parse Arguments let mut args = Arguments::from_env(); - let fuzz_spec_file: String = args - .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(); + let fuzz_spec_file: String = args.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(); + let workspace: String = args + .value_from_str("--workspace") + .unwrap_or("./workspace".to_string()); + let mut artifacts_path = PathBuf::from(workspace); + artifacts_path.push(&contract_name); + artifacts_path.push(&function_name); + artifacts_path.push("artifacts"); // Parse fuzz spec let contents = std::fs::read_to_string(fuzz_spec_file).unwrap(); let specs = fuzz_specs_from_json(&contents).unwrap(); - let (template_str, signature) = extract_template_and_signature(specs, &contract_name, &function_name).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(); let abi = SignatureAbi::from_signature(signature).unwrap(); + + FUZZ_CONFIG.replace(Some(FuzzConfig { template, abi })); + + // Create an observation channel using the signals map + // TODO: Collect coverage info from the semantics and modify SIGNALS to reflect changes + let observer = unsafe { StdMapObserver::new("signals", &mut SIGNALS) }; + + // Feedback that rates what's interesting from the observer + let mut feedback = MaxMapFeedback::new(&observer); + + // Feedback that rates what's a "solution" (test failure) + let mut objective = CrashFeedback::new(); + + // The State holds data that evolves over fuzzing, like the RNG state, + // the corpus, and metadata. + let mut state = StdState::new( + // RNG + StdRand::new(), + // Corpus that will save interesting test cases. In memory for now + // TODO: Save to disk once coverage updates are working. + InMemoryCorpus::::new(), + // Corpus folder in which we store solutions (test failures for us) + OnDiskCorpus::new(artifacts_path).unwrap(), + &mut feedback, + &mut objective, + ) + .unwrap(); + + // The Monitor trait defines how the fuzzer stats are displayed to the user + let mon = SimpleMonitor::new(|s| println!("{s}")); + + // The event manager handles the various events generated during the fuzzing loop + // such as the notification of the addition of a new item to the corpus + let mut mgr = SimpleEventManager::new(mon); + + // A queue policy to get testcases from the corpus + let scheduler = QueueScheduler::new(); + + // A fuzzer with feedbacks and a corpus scheduler + let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); + + // The executor which runs the harness + let mut harness_binding = harness; + let mut executor = InProcessExecutor::new( + &mut harness_binding, + tuple_list!(observer), + &mut fuzzer, + &mut state, + &mut mgr, + ) + .expect("Failed to create the Executor"); + + // The random bytes generator. Generates bytearrays up to length 1024 + let mut generator = RandPrintablesGenerator::new(nonzero!(1024)); + + // Generate initial inputs + state + .generate_initial_inputs(&mut fuzzer, &mut executor, &mut generator, &mut mgr, 100) + .expect("Failed to generate the initial corpus"); + + // Setup a mutational stage with a basic bytes mutator + let mutator = HavocScheduledMutator::new(havoc_mutations()); + let mut stages = tuple_list!(StdMutationalStage::new(mutator)); + + fuzzer + .fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr) + .expect("Error in the fuzzing loop"); +} + +fn harness(data: &BytesInput) -> ExitKind { + 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(); + + // Marshal over to kllvm with the CALLDATA variable substituted + let mut u = Unstructured::new(data.as_ref()); + 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(); + + // Execute the semantics + let mut block: kllvm::Block = kllvm_pattern.into(); + block.take_steps(-1); + + FUZZ_CONFIG.replace(config_cell); + MARSHALLER.replace(marshaller_cell); + + // Check the exit code + let exit_code = get_exit_code(&block); + if exit_code != 0 { + ExitKind::Crash + } else { + ExitKind::Ok + } } From 15bacaba362aa20e1444d104b4f9aec6cc667be2 Mon Sep 17 00:00:00 2001 From: Guy Repta <50716988+gtrepta@users.noreply.github.com> Date: Thu, 14 May 2026 20:03:23 -0500 Subject: [PATCH 05/10] feat: Add stubs for coverage reporting --- skribe-fuzz-rs/bin/skribe_fuzz.rs | 31 +++++++++++++++++++++---------- skribe-fuzz-rs/src/lib.rs | 10 ++++++++++ 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/skribe-fuzz-rs/bin/skribe_fuzz.rs b/skribe-fuzz-rs/bin/skribe_fuzz.rs index 3a6f12e..238ea7e 100644 --- a/skribe-fuzz-rs/bin/skribe_fuzz.rs +++ b/skribe-fuzz-rs/bin/skribe_fuzz.rs @@ -1,16 +1,15 @@ -#![allow(static_mut_refs)] - use arbitrary::Unstructured; use pico_args::Arguments; use skribe_fuzz_rs::{ FuzzConfig, SignatureAbi, SignatureFuzzer, extract_template_and_signature, - fuzz_specs_from_json, get_exit_code, + fuzz_specs_from_json, get_coverage_size, get_exit_code, kllvm::{self, Marshaller}, - kore, + kore, write_coverage_data, }; use std::cell::Cell; use std::path::PathBuf; +use std::ptr; use libafl::{ Fuzzer, StdFuzzer, @@ -30,9 +29,10 @@ use libafl::{ }; use libafl_bolts::{rands::StdRand, tuples::tuple_list}; -// Byte array for the coverage updates -// TODO: Determine a proper length for this -static mut SIGNALS: [u8; 16] = [0; 16]; +// Byte array pointer/size for the coverage updates +// Initialized on startup +static mut SIGNALS_PTR: *mut u8 = ptr::null_mut(); +static mut SIGNALS_LEN: usize = 0; // Persistent data across iterations. // @@ -71,11 +71,18 @@ fn main() { let abi = SignatureAbi::from_signature(signature).unwrap(); + let coverage_size = get_coverage_size(&template); + FUZZ_CONFIG.replace(Some(FuzzConfig { template, abi })); - // Create an observation channel using the signals map - // TODO: Collect coverage info from the semantics and modify SIGNALS to reflect changes - let observer = unsafe { StdMapObserver::new("signals", &mut SIGNALS) }; + // Create an observation channel for coverage + let alloc = vec![0u8; coverage_size].into_boxed_slice(); + let leaked: &'static mut [u8] = Box::leak(alloc); + unsafe { + SIGNALS_PTR = leaked.as_mut_ptr(); + SIGNALS_LEN = leaked.len(); + } + let observer = unsafe { StdMapObserver::from_mut_ptr("signals", SIGNALS_PTR, SIGNALS_LEN) }; // Feedback that rates what's interesting from the observer let mut feedback = MaxMapFeedback::new(&observer); @@ -160,6 +167,10 @@ fn harness(data: &BytesInput) -> ExitKind { FUZZ_CONFIG.replace(config_cell); MARSHALLER.replace(marshaller_cell); + // Record coverage for this run + let signals: &mut [u8] = unsafe { std::slice::from_raw_parts_mut(SIGNALS_PTR, SIGNALS_LEN) }; + write_coverage_data(&block, signals); + // Check the exit code let exit_code = get_exit_code(&block); if exit_code != 0 { diff --git a/skribe-fuzz-rs/src/lib.rs b/skribe-fuzz-rs/src/lib.rs index 64b169d..2878421 100644 --- a/skribe-fuzz-rs/src/lib.rs +++ b/skribe-fuzz-rs/src/lib.rs @@ -20,3 +20,13 @@ pub fn get_exit_code(block: &kllvm::Block) -> u32 { num_str.parse().unwrap() } + +pub fn write_coverage_data(block: &kllvm::Block, coverage: &mut [u8]) { + // Update coverage + // This should come in as a zeroed byte array every time, as it gets reset + // by the observer at the beginning of each execution +} + +pub fn get_coverage_size(config: &kore::Pattern) -> usize { + 100 +} From a3bdceac929f9110c599a41bece79d27f6ee98c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20T=C3=B3th?= Date: Fri, 15 May 2026 14:20:28 +0000 Subject: [PATCH 06/10] workaround: Spawn thread with increased stack size This is a workaround for increased term depth in the K configuration caused by the representation of coverage results. --- skribe-fuzz-rs/bin/skribe_fuzz.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/skribe-fuzz-rs/bin/skribe_fuzz.rs b/skribe-fuzz-rs/bin/skribe_fuzz.rs index 238ea7e..7cd8322 100644 --- a/skribe-fuzz-rs/bin/skribe_fuzz.rs +++ b/skribe-fuzz-rs/bin/skribe_fuzz.rs @@ -45,6 +45,19 @@ thread_local! { } fn main() { + std::panic::set_hook(Box::new(|info| { + eprintln!("{}", info); + })); + + let builder = std::thread::Builder::new().stack_size(64 * 1024 * 1024); // 64MB + let handler = builder.spawn(actual_main).unwrap(); + + if handler.join().is_err() { + std::process::exit(1); + } +} + +fn actual_main() { kllvm::init(); // Parse Arguments From b4f6b830b56d07a94e193f778289eaee4621855e Mon Sep 17 00:00:00 2001 From: Guy Repta <50716988+gtrepta@users.noreply.github.com> Date: Fri, 15 May 2026 13:10:46 -0500 Subject: [PATCH 07/10] fix: Add a single corpus entry to the state --- skribe-fuzz-rs/bin/skribe_fuzz.rs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/skribe-fuzz-rs/bin/skribe_fuzz.rs b/skribe-fuzz-rs/bin/skribe_fuzz.rs index 7cd8322..13d1a08 100644 --- a/skribe-fuzz-rs/bin/skribe_fuzz.rs +++ b/skribe-fuzz-rs/bin/skribe_fuzz.rs @@ -13,19 +13,17 @@ use std::ptr; use libafl::{ Fuzzer, StdFuzzer, - corpus::{InMemoryCorpus, OnDiskCorpus}, + corpus::{Corpus, InMemoryCorpus, OnDiskCorpus, Testcase}, events::SimpleEventManager, executors::{ExitKind, InProcessExecutor}, feedbacks::{CrashFeedback, MaxMapFeedback}, - generators::RandPrintablesGenerator, inputs::BytesInput, monitors::SimpleMonitor, mutators::{HavocScheduledMutator, havoc_mutations}, - nonzero, observers::StdMapObserver, schedulers::QueueScheduler, stages::StdMutationalStage, - state::StdState, + state::{HasCorpus, StdState}, }; use libafl_bolts::{rands::StdRand, tuples::tuple_list}; @@ -142,13 +140,12 @@ fn actual_main() { ) .expect("Failed to create the Executor"); - // The random bytes generator. Generates bytearrays up to length 1024 - let mut generator = RandPrintablesGenerator::new(nonzero!(1024)); - - // Generate initial inputs + // Initialize the corpus with a single byte array that will be mutated + // repeatedly. state - .generate_initial_inputs(&mut fuzzer, &mut executor, &mut generator, &mut mgr, 100) - .expect("Failed to generate the initial corpus"); + .corpus_mut() + .add(Testcase::new(BytesInput::new(vec![0u8; 1024]))) + .expect("Failed to initalize corpus"); // Setup a mutational stage with a basic bytes mutator let mutator = HavocScheduledMutator::new(havoc_mutations()); From 0c74029ec15c859015fb32c59a2a18467a924e9c Mon Sep 17 00:00:00 2001 From: Guy Repta <50716988+gtrepta@users.noreply.github.com> Date: Fri, 15 May 2026 13:27:00 -0500 Subject: [PATCH 08/10] feat: Add `--iterations` to `skribe-fuzz` --- skribe-fuzz-rs/bin/skribe_fuzz.rs | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/skribe-fuzz-rs/bin/skribe_fuzz.rs b/skribe-fuzz-rs/bin/skribe_fuzz.rs index 13d1a08..eed3bcc 100644 --- a/skribe-fuzz-rs/bin/skribe_fuzz.rs +++ b/skribe-fuzz-rs/bin/skribe_fuzz.rs @@ -20,6 +20,7 @@ use libafl::{ inputs::BytesInput, monitors::SimpleMonitor, mutators::{HavocScheduledMutator, havoc_mutations}, + nonzero, observers::StdMapObserver, schedulers::QueueScheduler, stages::StdMutationalStage, @@ -70,6 +71,7 @@ fn actual_main() { artifacts_path.push(&contract_name); artifacts_path.push(&function_name); artifacts_path.push("artifacts"); + let iterations: Option = args.opt_value_from_str("--iterations").unwrap_or(None); // Parse fuzz spec let contents = std::fs::read_to_string(fuzz_spec_file).unwrap(); @@ -149,11 +151,22 @@ fn actual_main() { // Setup a mutational stage with a basic bytes mutator let mutator = HavocScheduledMutator::new(havoc_mutations()); - let mut stages = tuple_list!(StdMutationalStage::new(mutator)); - - fuzzer - .fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr) - .expect("Error in the fuzzing loop"); + let mut stages = tuple_list!(StdMutationalStage::with_max_iterations( + mutator, + nonzero!(1) + )); + + if let Some(iterations) = iterations { + println!("Executing for {} iterations", iterations); + fuzzer + .fuzz_loop_for(&mut stages, &mut executor, &mut state, &mut mgr, iterations) + .expect("Error in the fuzzing loop"); + } else { + println!("Executing indefinitely"); + fuzzer + .fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr) + .expect("Error in the fuzzing loop"); + } } fn harness(data: &BytesInput) -> ExitKind { From 54db36b423de9fb72cab27fab04f94c8cf717489 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20T=C3=B3th?= Date: Fri, 15 May 2026 17:23:13 +0000 Subject: [PATCH 09/10] fix: Update `kframework-rs` to version `a3ca113` --- skribe-fuzz-rs/Cargo.lock | 2 ++ skribe-fuzz-rs/Cargo.toml | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/skribe-fuzz-rs/Cargo.lock b/skribe-fuzz-rs/Cargo.lock index dac1b0b..5abbf1c 100644 --- a/skribe-fuzz-rs/Cargo.lock +++ b/skribe-fuzz-rs/Cargo.lock @@ -1421,6 +1421,7 @@ dependencies = [ [[package]] name = "kframework" version = "0.1.0" +source = "git+https://github.com/runtimeverification/kframework-rs.git?rev=a3ca113#a3ca113278188a3bdc7c525c7d712bb0173e0eda" dependencies = [ "clap", "serde", @@ -1430,6 +1431,7 @@ dependencies = [ [[package]] name = "kframework_ffi" version = "0.1.0" +source = "git+https://github.com/runtimeverification/kframework-rs.git?rev=a3ca113#a3ca113278188a3bdc7c525c7d712bb0173e0eda" dependencies = [ "bindgen", "kframework", diff --git a/skribe-fuzz-rs/Cargo.toml b/skribe-fuzz-rs/Cargo.toml index 4d177cd..f4f7b3a 100644 --- a/skribe-fuzz-rs/Cargo.toml +++ b/skribe-fuzz-rs/Cargo.toml @@ -12,8 +12,8 @@ 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" } +kframework = { git = "https://github.com/runtimeverification/kframework-rs.git", rev = "a3ca113" } +kframework_ffi = { git = "https://github.com/runtimeverification/kframework-rs.git", rev = "a3ca113" } libafl = "0.15.4" libafl_bolts = "0.15.4" libfuzzer-sys = "0.4" From 9655a0b73ba3f9578d34f520038ede429a9f5384 Mon Sep 17 00:00:00 2001 From: devops Date: Fri, 15 May 2026 14:29:52 +0000 Subject: [PATCH 10/10] Set Version: 0.1.40 --- 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 528bd04..7172442 100644 --- a/package/version +++ b/package/version @@ -1 +1 @@ -0.1.39 +0.1.40 diff --git a/pyproject.toml b/pyproject.toml index 4adeeb3..28fd94a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "skribe" -version = "0.1.39" +version = "0.1.40" description = "Property testing for Stylus smart contracts" readme = "README.md" requires-python = "~=3.10" diff --git a/uv.lock b/uv.lock index e47ce23..a021e46 100644 --- a/uv.lock +++ b/uv.lock @@ -1886,7 +1886,7 @@ wheels = [ [[package]] name = "skribe" -version = "0.1.39" +version = "0.1.40" source = { editable = "." } dependencies = [ { name = "kontrol" },