From ade4d07bb5351f56be38547ed7e13848bba3b081 Mon Sep 17 00:00:00 2001 From: Arthur Carcano Date: Tue, 28 Apr 2026 15:46:17 +0200 Subject: [PATCH] Set up fuzz infrastructure --- Cargo.lock | 42 ++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 2 ++ fuzz/.gitignore | 4 ++++ fuzz/Cargo.toml | 20 ++++++++++++++++++++ src/model/Cargo.toml | 2 ++ src/util/Cargo.toml | 2 ++ src/util/crdt/lww.rs | 5 +++++ src/util/data.rs | 1 + 8 files changed, 78 insertions(+) create mode 100644 fuzz/.gitignore create mode 100644 fuzz/Cargo.toml diff --git a/Cargo.lock b/Cargo.lock index a8621e8d..2e5d4211 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -145,6 +145,15 @@ version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" +dependencies = [ + "derive_arbitrary", +] + [[package]] name = "arc-swap" version = "1.9.1" @@ -1116,6 +1125,17 @@ dependencies = [ "powerfmt", ] +[[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.114", +] + [[package]] name = "derive_more" version = "2.1.1" @@ -1523,6 +1543,16 @@ dependencies = [ "utoipa", ] +[[package]] +name = "garage-fuzz" +version = "0.0.0" +dependencies = [ + "arbitrary", + "garage_model", + "garage_table", + "libfuzzer-sys", +] + [[package]] name = "garage_api_admin" version = "2.3.0" @@ -1702,6 +1732,7 @@ dependencies = [ name = "garage_model" version = "2.3.0" dependencies = [ + "arbitrary", "argon2", "async-trait", "base64 0.22.1", @@ -1810,6 +1841,7 @@ dependencies = [ name = "garage_util" version = "2.3.0" dependencies = [ + "arbitrary", "arc-swap", "async-trait", "blake2", @@ -2934,6 +2966,16 @@ version = "0.2.185" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" +[[package]] +name = "libfuzzer-sys" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f12a681b7dd8ce12bff52488013ba614b869148d54dd79836ab85aafdd53f08d" +dependencies = [ + "arbitrary", + "cc", +] + [[package]] name = "libsodium-sys" version = "0.2.7" diff --git a/Cargo.toml b/Cargo.toml index 9cd06778..d6876b15 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ members = [ "src/garage", "src/k2v-client", "src/format-table", + "fuzz", ] default-members = ["src/garage"] @@ -40,6 +41,7 @@ k2v-client = { version = "0.0.4", path = "src/k2v-client" } # External crates from crates.io arc-swap = "1.8" +arbitrary = { version = "1.4.2", features = ["derive"] } argon2 = "0.5" async-trait = "0.1" backtrace = "0.3" diff --git a/fuzz/.gitignore b/fuzz/.gitignore new file mode 100644 index 00000000..1a45eee7 --- /dev/null +++ b/fuzz/.gitignore @@ -0,0 +1,4 @@ +target +corpus +artifacts +coverage diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml new file mode 100644 index 00000000..b5cb21e5 --- /dev/null +++ b/fuzz/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "garage-fuzz" +version = "0.0.0" +publish = false +edition = "2018" + +[package.metadata] +cargo-fuzz = true + +[dependencies] +arbitrary = { version = "1.4.2", features = ["derive"] } +libfuzzer-sys = "0.4" + +[dependencies.garage_table] +path = "../src/table" + +[dependencies.garage_model] +path = "../src/model" +features = ["arbitrary"] + diff --git a/src/model/Cargo.toml b/src/model/Cargo.toml index 12683a0e..bb3d9aac 100644 --- a/src/model/Cargo.toml +++ b/src/model/Cargo.toml @@ -21,6 +21,7 @@ garage_block.workspace = true garage_util.workspace = true garage_net.workspace = true +arbitrary = { optional = true, workspace = true } argon2.workspace = true async-trait.workspace = true blake2.workspace = true @@ -46,6 +47,7 @@ k2v = ["garage_util/k2v"] lmdb = ["garage_db/lmdb"] sqlite = ["garage_db/sqlite"] fjall = ["garage_db/fjall"] +arbitrary = ["dep:arbitrary","garage_util/arbitrary"] [lints] workspace = true diff --git a/src/util/Cargo.toml b/src/util/Cargo.toml index cbba213c..37799fd7 100644 --- a/src/util/Cargo.toml +++ b/src/util/Cargo.toml @@ -17,6 +17,7 @@ path = "lib.rs" garage_db.workspace = true garage_net.workspace = true +arbitrary = { optional = true, workspace = true } arc-swap.workspace = true async-trait.workspace = true blake2.workspace = true @@ -52,6 +53,7 @@ mktemp.workspace = true [features] k2v = [] +arbitrary = ["dep:arbitrary"] [lints] workspace = true diff --git a/src/util/crdt/lww.rs b/src/util/crdt/lww.rs index f8b03b85..e18ab5f3 100644 --- a/src/util/crdt/lww.rs +++ b/src/util/crdt/lww.rs @@ -84,6 +84,11 @@ where self.v = new_value; } + pub fn update2(&mut self, f: impl FnOnce(&mut T), time: u64) { + self.ts = std::cmp::max(self.ts + 1, time); + f(&mut self.v) + } + /// Get the timestamp currently associated with the value pub fn timestamp(&self) -> u64 { self.ts diff --git a/src/util/data.rs b/src/util/data.rs index e4ce316b..63c4379f 100644 --- a/src/util/data.rs +++ b/src/util/data.rs @@ -6,6 +6,7 @@ use std::fmt; /// An array of 32 bytes #[derive(Default, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Copy)] +#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] pub struct FixedBytes32([u8; 32]); impl From<[u8; 32]> for FixedBytes32 {