Skip to content

Commit 3abd567

Browse files
committed
Merge rust-bitcoin#5029: Add arbitrary_witness and parse_int fuzz targets
3f20f06 Add `arbitrary_witness` and `parse_int` fuzz targets (Shing Him Ng) 3239696 Bump honggfuzz to 0.5.58 (Shing Him Ng) Pull request description: ACKs for top commit: apoelstra: ACK 3f20f06; successfully ran local tests tcharding: ACK 3f20f06 Tree-SHA512: a0206bd1d9b4cf585738574eb33209f363981ffefa7cca2d72dc3b4e8869c1b328876b8d68d26f803d352f7d084726eb65e8250e9611320c675f88062119389b
2 parents 0df6b1e + 3f20f06 commit 3abd567

File tree

7 files changed

+181
-6
lines changed

7 files changed

+181
-6
lines changed

.github/workflows/cron-daily-fuzz.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ jobs:
2121
bitcoin_arbitrary_block,
2222
bitcoin_arbitrary_script,
2323
bitcoin_arbitrary_transaction,
24+
bitcoin_arbitrary_witness,
2425
bitcoin_deserialize_block,
2526
bitcoin_deserialize_prefilled_transaction,
2627
bitcoin_deserialize_psbt,
@@ -41,6 +42,7 @@ jobs:
4142
p2p_deserialize_raw_net_msg,
4243
units_arbitrary_weight,
4344
units_parse_amount,
45+
units_parse_int,
4446
]
4547
steps:
4648
- name: Install test dependencies

Cargo-minimal.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,9 @@ checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd"
251251

252252
[[package]]
253253
name = "honggfuzz"
254-
version = "0.5.57"
254+
version = "0.5.58"
255255
source = "registry+https://github.com/rust-lang/crates.io-index"
256-
checksum = "fc563d4f41b17364d5c48ded509f2bcf1c3f6ae9c7f203055b4a5c325072d57e"
256+
checksum = "6e8319f3cc8fe416e7aa1ab95dcc04fd49f35397a47d0b2f0f225f6dba346a07"
257257
dependencies = [
258258
"lazy_static",
259259
"memmap2",

Cargo-recent.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,9 +253,9 @@ checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd"
253253

254254
[[package]]
255255
name = "honggfuzz"
256-
version = "0.5.57"
256+
version = "0.5.58"
257257
source = "registry+https://github.com/rust-lang/crates.io-index"
258-
checksum = "fc563d4f41b17364d5c48ded509f2bcf1c3f6ae9c7f203055b4a5c325072d57e"
258+
checksum = "6e8319f3cc8fe416e7aa1ab95dcc04fd49f35397a47d0b2f0f225f6dba346a07"
259259
dependencies = [
260260
"lazy_static",
261261
"memmap2",

fuzz/Cargo.toml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ publish = false
1010
cargo-fuzz = true
1111

1212
[dependencies]
13-
honggfuzz = { version = "0.5.57", default-features = false }
13+
honggfuzz = { version = "0.5.58", default-features = false }
1414
bitcoin = { path = "../bitcoin", features = [ "serde", "arbitrary" ] }
1515
p2p = { path = "../p2p", package = "bitcoin-p2p-messages", features = ["arbitrary"] }
1616
arbitrary = { version = "1.4.1" }
@@ -33,6 +33,10 @@ path = "fuzz_targets/bitcoin/arbitrary_script.rs"
3333
name = "bitcoin_arbitrary_transaction"
3434
path = "fuzz_targets/bitcoin/arbitrary_transaction.rs"
3535

36+
[[bin]]
37+
name = "bitcoin_arbitrary_witness"
38+
path = "fuzz_targets/bitcoin/arbitrary_witness.rs"
39+
3640
[[bin]]
3741
name = "bitcoin_deserialize_block"
3842
path = "fuzz_targets/bitcoin/deserialize_block.rs"
@@ -112,3 +116,7 @@ path = "fuzz_targets/units/arbitrary_weight.rs"
112116
[[bin]]
113117
name = "units_parse_amount"
114118
path = "fuzz_targets/units/parse_amount.rs"
119+
120+
[[bin]]
121+
name = "units_parse_int"
122+
path = "fuzz_targets/units/parse_int.rs"
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
use arbitrary::{Arbitrary, Unstructured};
2+
use honggfuzz::fuzz;
3+
use bitcoin::consensus::{deserialize, serialize};
4+
use bitcoin::Witness;
5+
use bitcoin::blockdata::witness::WitnessExt;
6+
7+
fn do_test(data: &[u8]) {
8+
let mut u = Unstructured::new(data);
9+
10+
if let Ok(mut witness) = Witness::arbitrary(&mut u) {
11+
let serialized = serialize(&witness);
12+
13+
let _ = witness.witness_script();
14+
let _ = witness.taproot_leaf_script();
15+
16+
let deserialized: Result<Witness, _> = deserialize(serialized.as_slice());
17+
assert!(deserialized.is_ok(), "Deserialization error: {:?}", deserialized.err().unwrap());
18+
assert_eq!(deserialized.unwrap(), witness);
19+
20+
if let Ok(element_bytes) = Vec::<u8>::arbitrary(&mut u) {
21+
witness.push(element_bytes.as_slice());
22+
}
23+
}
24+
}
25+
26+
fn main() {
27+
loop {
28+
fuzz!(|data| {
29+
do_test(data);
30+
});
31+
}
32+
}
33+
34+
#[cfg(all(test, fuzzing))]
35+
mod tests {
36+
fn extend_vec_from_hex(hex: &str, out: &mut Vec<u8>) {
37+
let mut b = 0;
38+
for (idx, c) in hex.as_bytes().iter().enumerate() {
39+
b <<= 4;
40+
match *c {
41+
b'A'..=b'F' => b |= c - b'A' + 10,
42+
b'a'..=b'f' => b |= c - b'a' + 10,
43+
b'0'..=b'9' => b |= c - b'0',
44+
_ => panic!("Bad hex"),
45+
}
46+
if (idx & 1) == 1 {
47+
out.push(b);
48+
b = 0;
49+
}
50+
}
51+
}
52+
53+
#[test]
54+
fn duplicate_crash() {
55+
let mut a = Vec::new();
56+
extend_vec_from_hex("00", &mut a);
57+
super::do_test(&a);
58+
}
59+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
use arbitrary::Unstructured;
2+
use honggfuzz::fuzz;
3+
use bitcoin::parse_int;
4+
5+
fn do_test(data: &[u8]) {
6+
let mut u = Unstructured::new(data);
7+
8+
if let Ok(s) = u.arbitrary::<&str>() {
9+
let _ = parse_int::int_from_str::<i8>(s);
10+
let _ = parse_int::int_from_str::<i16>(s);
11+
let _ = parse_int::int_from_str::<i32>(s);
12+
let _ = parse_int::int_from_str::<i64>(s);
13+
let _ = parse_int::int_from_str::<i128>(s);
14+
15+
let _ = parse_int::int_from_str::<u8>(s);
16+
let _ = parse_int::int_from_str::<u16>(s);
17+
let _ = parse_int::int_from_str::<u32>(s);
18+
let _ = parse_int::int_from_str::<u64>(s);
19+
let _ = parse_int::int_from_str::<u128>(s);
20+
21+
let _ = parse_int::hex_remove_prefix(s);
22+
23+
if parse_int::hex_u32_prefixed(s).is_ok() {
24+
assert!(parse_int::hex_u32(s).is_ok());
25+
assert!(parse_int::hex_u32_unprefixed(s).is_err());
26+
}
27+
28+
if parse_int::hex_u32_unprefixed(s).is_ok() {
29+
assert!(parse_int::hex_u32(s).is_ok());
30+
assert!(parse_int::hex_u32_prefixed(s).is_err());
31+
}
32+
33+
if parse_int::hex_u128_prefixed(s).is_ok() {
34+
assert!(parse_int::hex_u128(s).is_ok());
35+
assert!(parse_int::hex_u128_unprefixed(s).is_err());
36+
}
37+
38+
if parse_int::hex_u128_unprefixed(s).is_ok() {
39+
assert!(parse_int::hex_u128(s).is_ok());
40+
assert!(parse_int::hex_u128_prefixed(s).is_err());
41+
}
42+
}
43+
44+
if let Ok(s) = u.arbitrary::<String>() {
45+
let _ = parse_int::int_from_string::<i8>(s.clone());
46+
let _ = parse_int::int_from_string::<i16>(s.clone());
47+
let _ = parse_int::int_from_string::<i32>(s.clone());
48+
let _ = parse_int::int_from_string::<i64>(s.clone());
49+
let _ = parse_int::int_from_string::<i128>(s.clone());
50+
51+
let _ = parse_int::int_from_string::<u8>(s.clone());
52+
let _ = parse_int::int_from_string::<u16>(s.clone());
53+
let _ = parse_int::int_from_string::<u32>(s.clone());
54+
let _ = parse_int::int_from_string::<u64>(s.clone());
55+
let _ = parse_int::int_from_string::<u128>(s);
56+
}
57+
58+
if let Ok(s) = u.arbitrary::<Box<str>>() {
59+
let _ = parse_int::int_from_box::<i8>(s.clone());
60+
let _ = parse_int::int_from_box::<i16>(s.clone());
61+
let _ = parse_int::int_from_box::<i32>(s.clone());
62+
let _ = parse_int::int_from_box::<i64>(s.clone());
63+
let _ = parse_int::int_from_box::<i128>(s.clone());
64+
65+
let _ = parse_int::int_from_box::<u8>(s.clone());
66+
let _ = parse_int::int_from_box::<u16>(s.clone());
67+
let _ = parse_int::int_from_box::<u32>(s.clone());
68+
let _ = parse_int::int_from_box::<u64>(s.clone());
69+
let _ = parse_int::int_from_box::<u128>(s);
70+
}
71+
}
72+
73+
fn main() {
74+
loop {
75+
fuzz!(|data| {
76+
do_test(data);
77+
});
78+
}
79+
}
80+
81+
#[cfg(all(test, fuzzing))]
82+
mod tests {
83+
fn extend_vec_from_hex(hex: &str, out: &mut Vec<u8>) {
84+
let mut b = 0;
85+
for (idx, c) in hex.as_bytes().iter().enumerate() {
86+
b <<= 4;
87+
match *c {
88+
b'A'..=b'F' => b |= c - b'A' + 10,
89+
b'a'..=b'f' => b |= c - b'a' + 10,
90+
b'0'..=b'9' => b |= c - b'0',
91+
_ => panic!("Bad hex"),
92+
}
93+
if (idx & 1) == 1 {
94+
out.push(b);
95+
b = 0;
96+
}
97+
}
98+
}
99+
100+
#[test]
101+
fn duplicate_crash() {
102+
let mut a = Vec::new();
103+
extend_vec_from_hex("00", &mut a);
104+
super::do_test(&a);
105+
}
106+
}

fuzz/generate-files.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ publish = false
2222
cargo-fuzz = true
2323
2424
[dependencies]
25-
honggfuzz = { version = "0.5.57", default-features = false }
25+
honggfuzz = { version = "0.5.58", default-features = false }
2626
bitcoin = { path = "../bitcoin", features = [ "serde", "arbitrary" ] }
2727
p2p = { path = "../p2p", package = "bitcoin-p2p-messages", features = ["arbitrary"] }
2828
arbitrary = { version = "1.4.1" }

0 commit comments

Comments
 (0)