fuzz: Add `hashes_arbitrary_json` target
What changed, and why it matters
This commit adds a new automated fuzz-testing target for the project's hash types. It does not change any production code, fix a bug, or alter behavior visible to users. It is purely a testing/infrastructure addition.
No security action required. This is a routine addition to the fuzzing suite. Reviewers may optionally verify that the new fuzz target compiles and runs in CI.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit introduces a new fuzz target named hashes_arbitrary_json that exercises round-trip JSON serialization/deserialization for several bitcoin::hashes types (HMAC-SHA1, HMAC-SHA512, RIPEMD160, SHA256d) using the arbitrary crate to generate structured inputs. The target is registered in fuzz/Cargo.toml and added to the daily fuzz CI workflow. No library code is modified.
Changed components
fuzz testing infrastructureCI workflow `.github/workflows/cron-daily-fuzz.yml`fuzz target `fuzz/fuzz_targets/hashes/arbitrary_json.rs`Inspect captured patch +58 / −0
diff --git a/.github/workflows/cron-daily-fuzz.yml b/.github/workflows/cron-daily-fuzz.yml
index c874d232..facd2ecf 100644
--- a/.github/workflows/cron-daily-fuzz.yml
+++ b/.github/workflows/cron-daily-fuzz.yml
@@ -105,6 +105,7 @@ jobs:
consensus_encoding_decode_byte_vec,
consensus_encoding_decode_compact_size,
consensus_encoding_decode_decoder2,
+ hashes_arbitrary_json,
hashes_json,
hashes_ripemd160,
hashes_sha1,
diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml
index 59e41c9f..95146ec9 100644
--- a/fuzz/Cargo.toml
+++ b/fuzz/Cargo.toml
@@ -650,6 +650,13 @@ test = false
doc = false
bench = false
+[[bin]]
+name = "hashes_arbitrary_json"
+path = "fuzz_targets/hashes/arbitrary_json.rs"
+test = false
+doc = false
+bench = false
+
[[bin]]
name = "hashes_json"
path = "fuzz_targets/hashes/json.rs"
diff --git a/fuzz/fuzz_targets/hashes/arbitrary_json.rs b/fuzz/fuzz_targets/hashes/arbitrary_json.rs
new file mode 100644
index 00000000..1d4e5b8e
--- /dev/null
+++ b/fuzz/fuzz_targets/hashes/arbitrary_json.rs
@@ -0,0 +1,50 @@
+#![cfg_attr(fuzzing, no_main)]
+#![cfg_attr(not(fuzzing), allow(unused))]
+
+use arbitrary::{Arbitrary, Unstructured};
+use bitcoin::hashes::{ripemd160, sha1, sha256d, sha512, Hmac};
+use libfuzzer_sys::fuzz_target;
+use serde::{Deserialize, Serialize};
+
+#[derive(Debug, PartialEq, Deserialize, Serialize)]
+struct Hmacs {
+ sha1: Hmac<sha1::Hash>,
+ sha512: Hmac<sha512::Hash>,
+}
+
+impl<'a> Arbitrary<'a> for Hmacs {
+ fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
+ Ok(Self {
+ sha1: u.arbitrary()?,
+ sha512: u.arbitrary()?,
+ })
+ }
+}
+
+#[derive(Debug, PartialEq, Deserialize, Serialize)]
+struct Main {
+ hmacs: Hmacs,
+ ripemd: ripemd160::Hash,
+ sha2d: sha256d::Hash,
+}
+
+impl<'a> Arbitrary<'a> for Main {
+ fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
+ Ok(Self {
+ hmacs: u.arbitrary()?,
+ ripemd: u.arbitrary()?,
+ sha2d: u.arbitrary()?,
+ })
+ }
+}
+
+#[cfg(not(fuzzing))]
+fn main() {}
+
+fn do_test(data: Main) {
+ let vec = serde_json::to_vec(&data).unwrap();
+ let reparsed = serde_json::from_slice::<Main>(&vec).unwrap();
+ assert_eq!(reparsed, data);
+}
+
+fuzz_target!(|data: Main| { do_test(data) });
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.