fuzz: migrate 0.32.x fuzz targets to master
What changed, and why it matters
This commit only adds and reorganizes fuzz testing code. It brings older 0.32.x fuzz targets onto the master branch and switches them from hongfuzz to libfuzzer. There are no changes to production library code, so ordinary users of the crate are not affected and no new security vulnerability is introduced.
No security action needed. Treat as routine testing infrastructure maintenance.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff is entirely within the fuzz/ directory, CI workflow, and lock files. It adds new fuzz targets for the 0.32.x line (consensus encoding comparison, network message deserialization, address/PSBT/outpoint parsing, CBOR hashes, amount deserialization), registers them in Cargo.toml and the daily fuzz workflow, bumps the pinned old_bitcoin dependency from 0.32.9 to 0.32.101, and pulls in serde_cbor. No runtime library code is modified.
Changed components
fuzz/fuzz_targetsfuzz/Cargo.tomlfuzz/generate-files.sh.github/workflows/cron-daily-fuzz.ymlCargo-minimal.lockCargo-recent.lockInspect captured patch +481 / −71
diff --git a/.github/workflows/cron-daily-fuzz.yml b/.github/workflows/cron-daily-fuzz.yml
index 1b66e0b5..e958e8a9 100644
--- a/.github/workflows/cron-daily-fuzz.yml
+++ b/.github/workflows/cron-daily-fuzz.yml
@@ -18,6 +18,11 @@ jobs:
fail-fast: false
matrix:
fuzz_target: [
+ bitcoin_0_32_compare_consensus_encoding,
+ bitcoin_0_32_deser_net_msg,
+ bitcoin_0_32_deserialize_address,
+ bitcoin_0_32_deserialize_psbt,
+ bitcoin_0_32_outpoint_string,
bitcoin_arbitrary_block,
bitcoin_arbitrary_script,
bitcoin_arbitrary_transaction,
@@ -61,6 +66,7 @@ jobs:
bitcoin_encoding_roundtrip_p2p_message_bloom_filter_load,
bitcoin_encoding_roundtrip_p2p_message_command_string,
bitcoin_encoding_roundtrip_p2p_message_compact_blocks_send_cmpct,
+ bitcoin_encoding_roundtrip_p2p_message_erlay_send_tx_rcn_cl,
bitcoin_encoding_roundtrip_p2p_message_fee_filter,
bitcoin_encoding_roundtrip_p2p_message_filter_c_f_checkpt,
bitcoin_encoding_roundtrip_p2p_message_filter_c_f_headers,
@@ -104,6 +110,7 @@ jobs:
consensus_encoding_decode_byte_vec,
consensus_encoding_decode_compact_size,
consensus_encoding_decode_decoder2,
+ hashes_0_32_cbor,
hashes_arbitrary_json,
hashes_json,
hashes_ripemd160,
@@ -114,6 +121,7 @@ jobs:
p2p_arbitrary_addrv2,
p2p_deserialize_addrv2,
p2p_deserialize_raw_net_msg,
+ units_0_32_deserialize_amount,
units_arbitrary_weight,
units_parse_amount,
units_parse_int,
diff --git a/Cargo-minimal.lock b/Cargo-minimal.lock
index 731daf68..4db2a6e9 100644
--- a/Cargo-minimal.lock
+++ b/Cargo-minimal.lock
@@ -16,12 +16,11 @@ checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
[[package]]
name = "base58ck"
-version = "0.1.0"
+version = "0.1.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c8d66485a3a2ea485c1913c4572ce0256067a5377ac8c75c4960e1cda98605f"
+checksum = "365c0acd5b2e8dd0111a46c4faea83fb3cfb6e39a49a7c73a06e090db7b2eff0"
dependencies = [
- "bitcoin-internals 0.3.0",
- "bitcoin_hashes 0.14.0",
+ "bitcoin_hashes 0.14.101",
]
[[package]]
@@ -57,19 +56,20 @@ dependencies = [
[[package]]
name = "bitcoin"
-version = "0.32.9"
+version = "0.32.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cf93e61f2dbc3e3c41234ca26a65e2c0b0975c52e0f069ab9893ebbede584d3"
+checksum = "8ed8ccb78a9ff7a6fbb90e2fb9b8588b4a9928d49d8af3cb789108a84ea6b0ce"
dependencies = [
- "base58ck 0.1.0",
+ "base58ck 0.1.101",
"bech32",
- "bitcoin-internals 0.3.0",
- "bitcoin-io 0.1.1",
- "bitcoin-units 0.1.0",
- "bitcoin_hashes 0.14.0",
+ "bitcoin-consensus-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitcoin-io 0.1.101",
+ "bitcoin-units 0.1.101",
+ "bitcoin_hashes 0.14.101",
"hex-conservative 0.2.2",
"hex_lit",
"secp256k1 0.29.0",
+ "serde",
]
[[package]]
@@ -81,7 +81,7 @@ dependencies = [
"base64",
"bech32",
"bincode",
- "bitcoin-consensus-encoding",
+ "bitcoin-consensus-encoding 1.0.0",
"bitcoin-crypto",
"bitcoin-internals 0.5.0",
"bitcoin-io 0.5.0",
@@ -117,6 +117,15 @@ dependencies = [
"serde_json",
]
+[[package]]
+name = "bitcoin-consensus-encoding"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2d6094e2a1ba3c93b5a596fe5a10d1a10c3c6e06785cde89f693a044c01aa40"
+dependencies = [
+ "bitcoin-internals 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "bitcoin-crypto"
version = "0.2.0"
@@ -138,22 +147,17 @@ name = "bitcoin-fuzz"
version = "0.0.1"
dependencies = [
"arbitrary",
- "bitcoin 0.32.9",
+ "bitcoin 0.32.101",
"bitcoin 0.33.0-beta",
- "bitcoin-consensus-encoding",
+ "bitcoin-consensus-encoding 1.0.0",
"bitcoin-p2p-messages",
"libfuzzer-sys",
"serde",
+ "serde_cbor",
"serde_json",
"standard_test",
]
-[[package]]
-name = "bitcoin-internals"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30bdbe14aa07b06e6cfeffc529a1f099e5fbe249524f8125358604df99a4bed2"
-
[[package]]
name = "bitcoin-internals"
version = "0.5.0"
@@ -164,17 +168,29 @@ dependencies = [
"serde_json",
]
+[[package]]
+name = "bitcoin-internals"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a30a22d1f112dde8e16be7b45c63645dc165cef254f835b3e1e9553e485cfa64"
+dependencies = [
+ "hex-conservative 0.3.0",
+]
+
[[package]]
name = "bitcoin-io"
-version = "0.1.1"
+version = "0.1.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17e5b76b88667412087beea1882980ad843b660490bbf6cce0a6cfc999c5b989"
+checksum = "bb5de036369d1ac59d3c1819ebc4d850f89466f5401c571a285b6ed564a4cb78"
+dependencies = [
+ "bitcoin-consensus-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
[[package]]
name = "bitcoin-io"
version = "0.5.0"
dependencies = [
- "bitcoin-consensus-encoding",
+ "bitcoin-consensus-encoding 1.0.0",
"bitcoin-internals 0.5.0",
"bitcoin_hashes 1.0.0",
]
@@ -212,7 +228,7 @@ name = "bitcoin-p2p-messages"
version = "0.1.0"
dependencies = [
"arbitrary",
- "bitcoin-consensus-encoding",
+ "bitcoin-consensus-encoding 1.0.0",
"bitcoin-internals 0.5.0",
"bitcoin-network-kind",
"bitcoin-primitives",
@@ -228,7 +244,7 @@ version = "0.102.0"
dependencies = [
"arbitrary",
"bincode",
- "bitcoin-consensus-encoding",
+ "bitcoin-consensus-encoding 1.0.0",
"bitcoin-internals 0.5.0",
"bitcoin-units 0.5.0",
"bitcoin_hashes 1.0.0",
@@ -256,11 +272,12 @@ dependencies = [
[[package]]
name = "bitcoin-units"
-version = "0.1.0"
+version = "0.1.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d437fd727271c866d6fd5e71eb2c886437d4c97f80d89246be3189b1da4e58b"
+checksum = "9cb95693f371d089a4b5b6fc41c6f3ea6e01ee8c15388335dfac8ea685173b51"
dependencies = [
- "bitcoin-internals 0.3.0",
+ "bitcoin-consensus-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde",
]
[[package]]
@@ -269,7 +286,7 @@ version = "0.5.0"
dependencies = [
"arbitrary",
"bincode",
- "bitcoin-consensus-encoding",
+ "bitcoin-consensus-encoding 1.0.0",
"bitcoin-internals 0.5.0",
"serde",
"serde_json",
@@ -287,12 +304,13 @@ dependencies = [
[[package]]
name = "bitcoin_hashes"
-version = "0.14.0"
+version = "0.14.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16"
+checksum = "bca4c7abb40c8817d77403c880988cfd484f23ab2365726afb2f798363e2c4a2"
dependencies = [
- "bitcoin-io 0.1.1",
+ "bitcoin-io 0.1.101",
"hex-conservative 0.2.2",
+ "serde",
]
[[package]]
@@ -300,7 +318,7 @@ name = "bitcoin_hashes"
version = "1.0.0"
dependencies = [
"arbitrary",
- "bitcoin-consensus-encoding",
+ "bitcoin-consensus-encoding 1.0.0",
"bitcoin-internals 0.5.0",
"cpufeatures",
"hex-conservative 1.1.0",
@@ -369,6 +387,12 @@ dependencies = [
"windows-targets",
]
+[[package]]
+name = "half"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a581f551b77eb3e177584e922a8c057e14311a857f859fd39d9574d97d3547da"
+
[[package]]
name = "hex-conservative"
version = "0.2.2"
@@ -378,6 +402,15 @@ dependencies = [
"arrayvec",
]
+[[package]]
+name = "hex-conservative"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4afe881d0527571892c4034822e59bb10c6c991cce6abe8199b6f5cf10766f55"
+dependencies = [
+ "arrayvec",
+]
+
[[package]]
name = "hex-conservative"
version = "1.1.0"
@@ -484,6 +517,7 @@ checksum = "0e0cc0f1cf93f4969faf3ea1c7d8a9faed25918d96affa959720823dfe86d4f3"
dependencies = [
"bitcoin_hashes 0.12.0",
"secp256k1-sys 0.10.0",
+ "serde",
]
[[package]]
@@ -525,6 +559,17 @@ dependencies = [
"serde_derive",
]
+[[package]]
+name = "serde_cbor"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45cd6d95391b16cd57e88b68be41d504183b7faae22030c0cc3b3f73dd57b2fd"
+dependencies = [
+ "byteorder",
+ "half",
+ "serde",
+]
+
[[package]]
name = "serde_derive"
version = "1.0.195"
diff --git a/Cargo-recent.lock b/Cargo-recent.lock
index 4c947df9..697397a7 100644
--- a/Cargo-recent.lock
+++ b/Cargo-recent.lock
@@ -16,12 +16,11 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]]
name = "base58ck"
-version = "0.1.0"
+version = "0.1.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c8d66485a3a2ea485c1913c4572ce0256067a5377ac8c75c4960e1cda98605f"
+checksum = "365c0acd5b2e8dd0111a46c4faea83fb3cfb6e39a49a7c73a06e090db7b2eff0"
dependencies = [
- "bitcoin-internals 0.3.0",
- "bitcoin_hashes 0.14.1",
+ "bitcoin_hashes 0.14.101",
]
[[package]]
@@ -56,19 +55,20 @@ dependencies = [
[[package]]
name = "bitcoin"
-version = "0.32.9"
+version = "0.32.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cf93e61f2dbc3e3c41234ca26a65e2c0b0975c52e0f069ab9893ebbede584d3"
+checksum = "8ed8ccb78a9ff7a6fbb90e2fb9b8588b4a9928d49d8af3cb789108a84ea6b0ce"
dependencies = [
- "base58ck 0.1.0",
+ "base58ck 0.1.101",
"bech32",
- "bitcoin-internals 0.3.0",
- "bitcoin-io 0.1.4",
- "bitcoin-units 0.1.3",
- "bitcoin_hashes 0.14.1",
+ "bitcoin-consensus-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitcoin-io 0.1.101",
+ "bitcoin-units 0.1.101",
+ "bitcoin_hashes 0.14.101",
"hex-conservative 0.2.2",
"hex_lit",
"secp256k1 0.29.1",
+ "serde",
]
[[package]]
@@ -80,7 +80,7 @@ dependencies = [
"base64",
"bech32",
"bincode",
- "bitcoin-consensus-encoding",
+ "bitcoin-consensus-encoding 1.0.0",
"bitcoin-crypto",
"bitcoin-internals 0.5.0",
"bitcoin-io 0.5.0",
@@ -116,6 +116,15 @@ dependencies = [
"serde_json",
]
+[[package]]
+name = "bitcoin-consensus-encoding"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2d6094e2a1ba3c93b5a596fe5a10d1a10c3c6e06785cde89f693a044c01aa40"
+dependencies = [
+ "bitcoin-internals 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "bitcoin-crypto"
version = "0.2.0"
@@ -137,22 +146,17 @@ name = "bitcoin-fuzz"
version = "0.0.1"
dependencies = [
"arbitrary",
- "bitcoin 0.32.9",
+ "bitcoin 0.32.101",
"bitcoin 0.33.0-beta",
- "bitcoin-consensus-encoding",
+ "bitcoin-consensus-encoding 1.0.0",
"bitcoin-p2p-messages",
"libfuzzer-sys",
"serde",
+ "serde_cbor",
"serde_json",
"standard_test",
]
-[[package]]
-name = "bitcoin-internals"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30bdbe14aa07b06e6cfeffc529a1f099e5fbe249524f8125358604df99a4bed2"
-
[[package]]
name = "bitcoin-internals"
version = "0.5.0"
@@ -163,17 +167,29 @@ dependencies = [
"serde_json",
]
+[[package]]
+name = "bitcoin-internals"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a30a22d1f112dde8e16be7b45c63645dc165cef254f835b3e1e9553e485cfa64"
+dependencies = [
+ "hex-conservative 0.3.2",
+]
+
[[package]]
name = "bitcoin-io"
-version = "0.1.4"
+version = "0.1.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dee39a0ee5b4095224a0cfc6bf4cc1baf0f9624b96b367e53b66d974e51d953"
+checksum = "bb5de036369d1ac59d3c1819ebc4d850f89466f5401c571a285b6ed564a4cb78"
+dependencies = [
+ "bitcoin-consensus-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
[[package]]
name = "bitcoin-io"
version = "0.5.0"
dependencies = [
- "bitcoin-consensus-encoding",
+ "bitcoin-consensus-encoding 1.0.0",
"bitcoin-internals 0.5.0",
"bitcoin_hashes 1.0.0",
]
@@ -211,7 +227,7 @@ name = "bitcoin-p2p-messages"
version = "0.1.0"
dependencies = [
"arbitrary",
- "bitcoin-consensus-encoding",
+ "bitcoin-consensus-encoding 1.0.0",
"bitcoin-internals 0.5.0",
"bitcoin-network-kind",
"bitcoin-primitives",
@@ -227,7 +243,7 @@ version = "0.102.0"
dependencies = [
"arbitrary",
"bincode",
- "bitcoin-consensus-encoding",
+ "bitcoin-consensus-encoding 1.0.0",
"bitcoin-internals 0.5.0",
"bitcoin-units 0.5.0",
"bitcoin_hashes 1.0.0",
@@ -249,11 +265,12 @@ dependencies = [
[[package]]
name = "bitcoin-units"
-version = "0.1.3"
+version = "0.1.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "346568ebaab2918487cea76dd55dae13c27bb618cdb737c952e69eb2017c4118"
+checksum = "9cb95693f371d089a4b5b6fc41c6f3ea6e01ee8c15388335dfac8ea685173b51"
dependencies = [
- "bitcoin-internals 0.3.0",
+ "bitcoin-consensus-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde",
]
[[package]]
@@ -262,7 +279,7 @@ version = "0.5.0"
dependencies = [
"arbitrary",
"bincode",
- "bitcoin-consensus-encoding",
+ "bitcoin-consensus-encoding 1.0.0",
"bitcoin-internals 0.5.0",
"serde",
"serde_json",
@@ -271,12 +288,13 @@ dependencies = [
[[package]]
name = "bitcoin_hashes"
-version = "0.14.1"
+version = "0.14.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26ec84b80c482df901772e931a9a681e26a1b9ee2302edeff23cb30328745c8b"
+checksum = "bca4c7abb40c8817d77403c880988cfd484f23ab2365726afb2f798363e2c4a2"
dependencies = [
- "bitcoin-io 0.1.4",
+ "bitcoin-io 0.1.101",
"hex-conservative 0.2.2",
+ "serde",
]
[[package]]
@@ -284,7 +302,7 @@ name = "bitcoin_hashes"
version = "1.0.0"
dependencies = [
"arbitrary",
- "bitcoin-consensus-encoding",
+ "bitcoin-consensus-encoding 1.0.0",
"bitcoin-internals 0.5.0",
"cpufeatures",
"hex-conservative 1.1.0",
@@ -352,6 +370,12 @@ dependencies = [
"wasip2",
]
+[[package]]
+name = "half"
+version = "1.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403"
+
[[package]]
name = "hex-conservative"
version = "0.2.2"
@@ -361,6 +385,15 @@ dependencies = [
"arrayvec",
]
+[[package]]
+name = "hex-conservative"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830e599c2904b08f0834ee6337d8fe8f0ed4a63b5d9e7a7f49c0ffa06d08d360"
+dependencies = [
+ "arrayvec",
+]
+
[[package]]
name = "hex-conservative"
version = "1.1.0"
@@ -487,8 +520,9 @@ version = "0.29.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113"
dependencies = [
- "bitcoin_hashes 0.14.1",
+ "bitcoin_hashes 0.14.101",
"secp256k1-sys 0.10.1",
+ "serde",
]
[[package]]
@@ -530,6 +564,17 @@ dependencies = [
"serde_derive",
]
+[[package]]
+name = "serde_cbor"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45cd6d95391b16cd57e88b68be41d504183b7faae22030c0cc3b3f73dd57b2fd"
+dependencies = [
+ "byteorder",
+ "half",
+ "serde",
+]
+
[[package]]
name = "serde_derive"
version = "1.0.210"
diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml
index 95146ec9..c54c9c60 100644
--- a/fuzz/Cargo.toml
+++ b/fuzz/Cargo.toml
@@ -13,7 +13,7 @@ cargo-fuzz = true
# We shouldn't need an explicit version on the next line, but Andrew's tools
# choke on it otherwise. See https://github.com/nix-community/crate2nix/issues/373
bitcoin = { path = "../bitcoin", version = "0.33.0-beta", features = [ "serde", "arbitrary" ] }
-old_bitcoin = { version = "0.32.9", package = "bitcoin" }
+old_bitcoin = { version = "0.32.101", package = "bitcoin", features = [ "encoding", "serde" ] }
bitcoin_consensus_encoding = { path = "../consensus_encoding", package = "bitcoin-consensus-encoding" }
p2p = { path = "../p2p", package = "bitcoin-p2p-messages", features = ["arbitrary"] }
@@ -21,6 +21,7 @@ arbitrary = { version = "1.4.1" }
libfuzzer-sys = { version = "0.4.0" }
serde = { version = "1.0.195", features = [ "derive" ] }
serde_json = "1.0.68"
+serde_cbor = "0.9"
standard_test = "0.1.0"
[lints.rust]
@@ -39,7 +40,7 @@ allowed_duplicates = [
"hex-conservative",
"bitcoin_hashes",
"bitcoin-io",
- "hex-conservative",
+ "bitcoin-consensus-encoding",
"base58ck",
"bitcoin",
"bitcoin-internals",
@@ -349,6 +350,13 @@ test = false
doc = false
bench = false
+[[bin]]
+name = "bitcoin_encoding_roundtrip_p2p_message_erlay_send_tx_rcn_cl"
+path = "fuzz_targets/bitcoin/encoding_roundtrip/p2p_message_erlay_send_tx_rcn_cl.rs"
+test = false
+doc = false
+bench = false
+
[[bin]]
name = "bitcoin_encoding_roundtrip_p2p_message_fee_filter"
path = "fuzz_targets/bitcoin/encoding_roundtrip/p2p_message_fee_filter.rs"
@@ -622,6 +630,41 @@ test = false
doc = false
bench = false
+[[bin]]
+name = "bitcoin_0_32_compare_consensus_encoding"
+path = "fuzz_targets/bitcoin_0_32/compare_consensus_encoding.rs"
+test = false
+doc = false
+bench = false
+
+[[bin]]
+name = "bitcoin_0_32_deser_net_msg"
+path = "fuzz_targets/bitcoin_0_32/deser_net_msg.rs"
+test = false
+doc = false
+bench = false
+
+[[bin]]
+name = "bitcoin_0_32_deserialize_address"
+path = "fuzz_targets/bitcoin_0_32/deserialize_address.rs"
+test = false
+doc = false
+bench = false
+
+[[bin]]
+name = "bitcoin_0_32_deserialize_psbt"
+path = "fuzz_targets/bitcoin_0_32/deserialize_psbt.rs"
+test = false
+doc = false
+bench = false
+
+[[bin]]
+name = "bitcoin_0_32_outpoint_string"
+path = "fuzz_targets/bitcoin_0_32/outpoint_string.rs"
+test = false
+doc = false
+bench = false
+
[[bin]]
name = "consensus_encoding_decode_array"
path = "fuzz_targets/consensus_encoding/decode_array.rs"
@@ -699,6 +742,13 @@ test = false
doc = false
bench = false
+[[bin]]
+name = "hashes_0_32_cbor"
+path = "fuzz_targets/hashes_0_32/cbor.rs"
+test = false
+doc = false
+bench = false
+
[[bin]]
name = "p2p_arbitrary_addrv2"
path = "fuzz_targets/p2p/arbitrary_addrv2.rs"
@@ -747,3 +797,10 @@ path = "fuzz_targets/units/standard_checks.rs"
test = false
doc = false
bench = false
+
+[[bin]]
+name = "units_0_32_deserialize_amount"
+path = "fuzz_targets/units_0_32/deserialize_amount.rs"
+test = false
+doc = false
+bench = false
diff --git a/fuzz/fuzz_targets/bitcoin/encoding_roundtrip/p2p_message_erlay_send_tx_rcn_cl.rs b/fuzz/fuzz_targets/bitcoin/encoding_roundtrip/p2p_message_erlay_send_tx_rcn_cl.rs
new file mode 100644
index 00000000..69800a00
--- /dev/null
+++ b/fuzz/fuzz_targets/bitcoin/encoding_roundtrip/p2p_message_erlay_send_tx_rcn_cl.rs
@@ -0,0 +1,12 @@
+#![cfg_attr(fuzzing, no_main)]
+#![cfg_attr(not(fuzzing), allow(unused))]
+
+use bitcoin_fuzz::check_roundtrip;
+use libfuzzer_sys::fuzz_target;
+
+#[cfg(not(fuzzing))]
+fn main() {}
+
+fuzz_target!(|data: &[u8]| {
+ check_roundtrip::<p2p::message_erlay::SendTxRcnCl>(data);
+});
diff --git a/fuzz/fuzz_targets/bitcoin_0_32/compare_consensus_encoding.rs b/fuzz/fuzz_targets/bitcoin_0_32/compare_consensus_encoding.rs
new file mode 100644
index 00000000..e84e8710
--- /dev/null
+++ b/fuzz/fuzz_targets/bitcoin_0_32/compare_consensus_encoding.rs
@@ -0,0 +1,63 @@
+#![cfg_attr(fuzzing, no_main)]
+#![cfg_attr(not(fuzzing), allow(unused))]
+
+use libfuzzer_sys::fuzz_target;
+use old_bitcoin::absolute;
+use old_bitcoin::consensus::encode::deserialize_partial;
+use old_bitcoin::consensus::serialize;
+use old_bitcoin::encoding::{self, decode_from_slice_unbounded};
+
+#[cfg(not(fuzzing))]
+fn main() {}
+
+macro_rules! compare_encoding {
+ ($data:expr, $ty:ident) => {
+ compare_encoding!($data, old_bitcoin::$ty);
+ };
+
+ ($data:expr, $ty:ty) => {{
+ // Use partial/unbounded decoding so the fuzzer can exercise the actual parsing
+ // logic even when the input is longer than the encoded type. Using strict
+ // deserialize() would reject any input with trailing bytes, reducing coverage.
+ let old_result = deserialize_partial::<$ty>($data);
+ let mut rem = &*$data;
+ let new_result: Result<$ty, _> = decode_from_slice_unbounded(&mut rem);
+
+ match (old_result, new_result) {
+ (Ok((old_obj, old_consumed)), Ok(new_obj)) => {
+ assert_eq!(old_obj, new_obj);
+ let new_consumed = $data.len() - rem.len();
+ assert_eq!(
+ old_consumed, new_consumed,
+ "decoders consumed different number of bytes: legacy={old_consumed}, new={new_consumed}"
+ );
+ let old_encoded = serialize(&old_obj);
+ let new_encoded = encoding::encode_to_vec(&new_obj);
+ assert_eq!(old_encoded, new_encoded);
+ }
+ (Err(_), Err(_)) => {}
+ (Ok((old_obj, _)), Err(err)) => {
+ panic!("legacy decoder accepted {old_obj:?}, new decoder failed: {err:?}");
+ }
+ (Err(err), Ok(new_obj)) => {
+ panic!("new decoder accepted {new_obj:?}, legacy decoder failed: {err:?}");
+ }
+ }
+ }};
+}
+
+fn do_test(data: &[u8]) {
+ // Split data evenly so the fuzzer can independently explore each type's input space.
+ // Each type gets its own non-overlapping sub-slice; `Amount` needs 8 bytes (u64 LE),
+ // the rest need 4 bytes (u32 LE). Trailing bytes in each slice are tolerated by the
+ // partial/unbounded decoders used in `compare_encoding!`.
+ let n = data.len() / 4;
+ compare_encoding!(&data[..n], Amount);
+ compare_encoding!(&data[n..2 * n], Sequence);
+ compare_encoding!(&data[2 * n..3 * n], CompactTarget);
+ compare_encoding!(&data[3 * n..4 * n], absolute::LockTime);
+}
+
+fuzz_target!(|data: &[u8]| {
+ do_test(data);
+});
diff --git a/fuzz/fuzz_targets/bitcoin_0_32/deser_net_msg.rs b/fuzz/fuzz_targets/bitcoin_0_32/deser_net_msg.rs
new file mode 100644
index 00000000..530487f3
--- /dev/null
+++ b/fuzz/fuzz_targets/bitcoin_0_32/deser_net_msg.rs
@@ -0,0 +1,16 @@
+#![cfg_attr(fuzzing, no_main)]
+#![cfg_attr(not(fuzzing), allow(unused))]
+
+use libfuzzer_sys::fuzz_target;
+
+#[cfg(not(fuzzing))]
+fn main() {}
+
+fn do_test(data: &[u8]) {
+ let _: Result<old_bitcoin::p2p::message::RawNetworkMessage, _> =
+ old_bitcoin::consensus::encode::deserialize(data);
+}
+
+fuzz_target!(|data: &[u8]| {
+ do_test(data);
+});
diff --git a/fuzz/fuzz_targets/bitcoin_0_32/deserialize_address.rs b/fuzz/fuzz_targets/bitcoin_0_32/deserialize_address.rs
new file mode 100644
index 00000000..ca15faa0
--- /dev/null
+++ b/fuzz/fuzz_targets/bitcoin_0_32/deserialize_address.rs
@@ -0,0 +1,20 @@
+#![cfg_attr(fuzzing, no_main)]
+#![cfg_attr(not(fuzzing), allow(unused))]
+
+use libfuzzer_sys::fuzz_target;
+
+#[cfg(not(fuzzing))]
+fn main() {}
+
+fn do_test(data: &[u8]) {
+ let data_str = String::from_utf8_lossy(data);
+ let addr = match data_str.parse::<old_bitcoin::address::Address<_>>() {
+ Ok(addr) => addr.assume_checked(),
+ Err(_) => return,
+ };
+ assert_eq!(addr.to_string(), data_str);
+}
+
+fuzz_target!(|data: &[u8]| {
+ do_test(data);
+});
diff --git a/fuzz/fuzz_targets/bitcoin_0_32/deserialize_psbt.rs b/fuzz/fuzz_targets/bitcoin_0_32/deserialize_psbt.rs
new file mode 100644
index 00000000..ecc69121
--- /dev/null
+++ b/fuzz/fuzz_targets/bitcoin_0_32/deserialize_psbt.rs
@@ -0,0 +1,24 @@
+#![cfg_attr(fuzzing, no_main)]
+#![cfg_attr(not(fuzzing), allow(unused))]
+
+use libfuzzer_sys::fuzz_target;
+
+#[cfg(not(fuzzing))]
+fn main() {}
+
+fn do_test(data: &[u8]) {
+ let psbt: Result<old_bitcoin::psbt::Psbt, _> = old_bitcoin::psbt::Psbt::deserialize(data);
+ match psbt {
+ Err(_) => {}
+ Ok(psbt) => {
+ let ser = old_bitcoin::psbt::Psbt::serialize(&psbt);
+ let deser = old_bitcoin::psbt::Psbt::deserialize(&ser).unwrap();
+ // Since the fuzz data could order psbt fields differently, we compare to our deser/ser instead of data
+ assert_eq!(ser, old_bitcoin::psbt::Psbt::serialize(&deser));
+ }
+ }
+}
+
+fuzz_target!(|data: &[u8]| {
+ do_test(data);
+});
diff --git a/fuzz/fuzz_targets/bitcoin_0_32/outpoint_string.rs b/fuzz/fuzz_targets/bitcoin_0_32/outpoint_string.rs
new file mode 100644
index 00000000..19ca07da
--- /dev/null
+++ b/fuzz/fuzz_targets/bitcoin_0_32/outpoint_string.rs
@@ -0,0 +1,49 @@
+#![cfg_attr(fuzzing, no_main)]
+#![cfg_attr(not(fuzzing), allow(unused))]
+
+use libfuzzer_sys::fuzz_target;
+
+#[cfg(not(fuzzing))]
+fn main() {}
+
+fn do_test(data: &[u8]) {
+ let lowercase: Vec<u8> = data
+ .iter()
+ .map(|c| match *c {
+ b'A' => b'a',
+ b'B' => b'b',
+ b'C' => b'c',
+ b'D' => b'd',
+ b'E' => b'e',
+ b'F' => b'f',
+ x => x,
+ })
+ .collect();
+ let data_str = match String::from_utf8(lowercase) {
+ Err(_) => return,
+ Ok(s) => s,
+ };
+ match data_str.parse::<old_bitcoin::blockdata::transaction::OutPoint>() {
+ Ok(op) => {
+ assert_eq!(op.to_string().as_bytes(), data_str.as_bytes());
+ }
+ Err(_) => {
+ // If we can't deserialize as a string, try consensus deserializing
+ let res: Result<old_bitcoin::blockdata::transaction::OutPoint, _> =
+ old_bitcoin::consensus::encode::deserialize(data);
+ if let Ok(deser) = res {
+ let ser = old_bitcoin::consensus::encode::serialize(&deser);
+ assert_eq!(ser, data);
+ let string = deser.to_string();
+ match string.parse::<old_bitcoin::blockdata::transaction::OutPoint>() {
+ Ok(destring) => assert_eq!(destring, deser),
+ Err(_) => panic!(),
+ }
+ }
+ }
+ }
+}
+
+fuzz_target!(|data: &[u8]| {
+ do_test(data);
+});
diff --git a/fuzz/fuzz_targets/hashes_0_32/cbor.rs b/fuzz/fuzz_targets/hashes_0_32/cbor.rs
new file mode 100644
index 00000000..bd95b367
--- /dev/null
+++ b/fuzz/fuzz_targets/hashes_0_32/cbor.rs
@@ -0,0 +1,32 @@
+#![cfg_attr(fuzzing, no_main)]
+#![cfg_attr(not(fuzzing), allow(unused))]
+
+use libfuzzer_sys::fuzz_target;
+use serde::{Deserialize, Serialize};
+
+#[derive(Deserialize, Serialize)]
+struct Hmacs {
+ sha1: old_bitcoin::hashes::hmac::Hmac<old_bitcoin::hashes::sha1::Hash>,
+ sha512: old_bitcoin::hashes::hmac::Hmac<old_bitcoin::hashes::sha512::Hash>,
+}
+
+#[derive(Deserialize, Serialize)]
+struct Main {
+ hmacs: Hmacs,
+ ripemd: old_bitcoin::hashes::ripemd160::Hash,
+ sha2d: old_bitcoin::hashes::sha256d::Hash,
+}
+
+#[cfg(not(fuzzing))]
+fn main() {}
+
+fn do_test(data: &[u8]) {
+ if let Ok(m) = serde_cbor::from_slice::<Main>(data) {
+ let vec = serde_cbor::to_vec(&m).unwrap();
+ assert_eq!(data, &vec[..]);
+ }
+}
+
+fuzz_target!(|data: &[u8]| {
+ do_test(data);
+});
diff --git a/fuzz/fuzz_targets/units_0_32/deserialize_amount.rs b/fuzz/fuzz_targets/units_0_32/deserialize_amount.rs
new file mode 100644
index 00000000..04f80417
--- /dev/null
+++ b/fuzz/fuzz_targets/units_0_32/deserialize_amount.rs
@@ -0,0 +1,38 @@
+#![cfg_attr(fuzzing, no_main)]
+#![cfg_attr(not(fuzzing), allow(unused))]
+
+use libfuzzer_sys::fuzz_target;
+use std::str::FromStr;
+
+#[cfg(not(fuzzing))]
+fn main() {}
+
+fn do_test(data: &[u8]) {
+ let data_str = String::from_utf8_lossy(data);
+
+ // signed
+ let samt = match old_bitcoin::amount::SignedAmount::from_str(&data_str) {
+ Ok(amt) => amt,
+ Err(_) => return,
+ };
+ let samt_roundtrip = match old_bitcoin::amount::SignedAmount::from_str(&samt.to_string()) {
+ Ok(amt) => amt,
+ Err(_) => return,
+ };
+ assert_eq!(samt, samt_roundtrip);
+
+ // unsigned
+ let amt = match old_bitcoin::amount::Amount::from_str(&data_str) {
+ Ok(amt) => amt,
+ Err(_) => return,
+ };
+ let amt_roundtrip = match old_bitcoin::amount::Amount::from_str(&amt.to_string()) {
+ Ok(amt) => amt,
+ Err(_) => return,
+ };
+ assert_eq!(amt, amt_roundtrip);
+}
+
+fuzz_target!(|data: &[u8]| {
+ do_test(data);
+});
diff --git a/fuzz/generate-files.sh b/fuzz/generate-files.sh
index 69b26d9d..770c6a46 100755
--- a/fuzz/generate-files.sh
+++ b/fuzz/generate-files.sh
@@ -26,7 +26,7 @@ cargo-fuzz = true
# We shouldn't need an explicit version on the next line, but Andrew's tools
# choke on it otherwise. See https://github.com/nix-community/crate2nix/issues/373
bitcoin = { path = "../bitcoin", version = "0.33.0-beta", features = [ "serde", "arbitrary" ] }
-old_bitcoin = { version = "0.32.9", package = "bitcoin" }
+old_bitcoin = { version = "0.32.101", package = "bitcoin", features = [ "encoding", "serde" ] }
bitcoin_consensus_encoding = { path = "../consensus_encoding", package = "bitcoin-consensus-encoding" }
p2p = { path = "../p2p", package = "bitcoin-p2p-messages", features = ["arbitrary"] }
@@ -34,6 +34,7 @@ arbitrary = { version = "1.4.1" }
libfuzzer-sys = { version = "0.4.0" }
serde = { version = "1.0.195", features = [ "derive" ] }
serde_json = "1.0.68"
+serde_cbor = "0.9"
standard_test = "0.1.0"
[lints.rust]
@@ -52,7 +53,7 @@ allowed_duplicates = [
"hex-conservative",
"bitcoin_hashes",
"bitcoin-io",
- "hex-conservative",
+ "bitcoin-consensus-encoding",
"base58ck",
"bitcoin",
"bitcoin-internals",
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.