From 64677282023295812c8b95212e0e5e96021040f2 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Wed, 22 Mar 2023 15:07:50 +0000 Subject: [PATCH] fuzz: disable tests unless 'cfg(fuzzing)' is passed; update README for reproducing failures --- fuzz/README.md | 25 +++++++++++++++++ fuzz/fuzz_targets/bitcoin/deser_net_msg.rs | 2 +- .../bitcoin/deserialize_address.rs | 2 +- .../bitcoin/deserialize_amount.rs | 2 +- .../fuzz_targets/bitcoin/deserialize_block.rs | 2 +- .../deserialize_prefilled_transaction.rs | 2 +- fuzz/fuzz_targets/bitcoin/deserialize_psbt.rs | 2 +- .../bitcoin/deserialize_script.rs | 2 +- .../bitcoin/deserialize_transaction.rs | 2 +- .../bitcoin/deserialize_witness.rs | 2 +- fuzz/fuzz_targets/bitcoin/outpoint_string.rs | 2 +- .../bitcoin/script_bytes_to_asm_fmt.rs | 27 +++++++++++++++++++ fuzz/fuzz_targets/hashes/cbor.rs | 2 +- fuzz/fuzz_targets/hashes/json.rs | 2 +- fuzz/fuzz_targets/hashes/ripemd160.rs | 2 +- fuzz/fuzz_targets/hashes/sha1.rs | 2 +- fuzz/fuzz_targets/hashes/sha256.rs | 4 +-- fuzz/fuzz_targets/hashes/sha512.rs | 2 +- fuzz/fuzz_targets/hashes/sha512_256.rs | 2 +- 19 files changed, 70 insertions(+), 18 deletions(-) diff --git a/fuzz/README.md b/fuzz/README.md index 8a5961fe..073457dc 100644 --- a/fuzz/README.md +++ b/fuzz/README.md @@ -65,4 +65,29 @@ If it is working, you will see a rapid stream of data for many seconds (you can hit Ctrl+C to stop it early). If not, you should quickly see an error. +# Reproducing Failures + +If a fuzztest fails, it will exit with a summary which looks something like + +``` +... + fuzzTarget : hfuzz_target/x86_64-unknown-linux-gnu/release/hashes_sha256 +CRASH: +DESCRIPTION: +ORIG_FNAME: 00000000000000000000000000000000.00000000.honggfuzz.cov +FUZZ_FNAME: hfuzz_workspace/hashes_sha256/SIGABRT.PC.7ffff7c8abc7.STACK.18826d9b64.CODE.-6.ADDR.0.INSTR.mov____%eax,%ebp.fuzz +... +===================================================================== +fff400610004 +``` + +The final line is a hex-encoded version of the input that caused the crash. You +can test this directly by editing the `duplicate_crash` test to copy/paste the +hex output into the call to `extend_vec_from_hex`. Then run the test with + + RUSTFLAGS=--cfg=fuzzing cargo test + +It is important to add the `cfg=fuzzing` flag, which tells rustc to compile the +library as though it were running a fuzztest. In particular, this will disable +or weaken all the cryptography. diff --git a/fuzz/fuzz_targets/bitcoin/deser_net_msg.rs b/fuzz/fuzz_targets/bitcoin/deser_net_msg.rs index a0024232..883431c1 100644 --- a/fuzz/fuzz_targets/bitcoin/deser_net_msg.rs +++ b/fuzz/fuzz_targets/bitcoin/deser_net_msg.rs @@ -13,7 +13,7 @@ fn main() { } } -#[cfg(test)] +#[cfg(all(test, fuzzing))] mod tests { fn extend_vec_from_hex(hex: &str, out: &mut Vec) { let mut b = 0; diff --git a/fuzz/fuzz_targets/bitcoin/deserialize_address.rs b/fuzz/fuzz_targets/bitcoin/deserialize_address.rs index 96bb45ab..56d1db64 100644 --- a/fuzz/fuzz_targets/bitcoin/deserialize_address.rs +++ b/fuzz/fuzz_targets/bitcoin/deserialize_address.rs @@ -19,7 +19,7 @@ fn main() { } } -#[cfg(test)] +#[cfg(all(test, fuzzing))] mod tests { fn extend_vec_from_hex(hex: &str, out: &mut Vec) { let mut b = 0; diff --git a/fuzz/fuzz_targets/bitcoin/deserialize_amount.rs b/fuzz/fuzz_targets/bitcoin/deserialize_amount.rs index 399bee87..febb0eec 100644 --- a/fuzz/fuzz_targets/bitcoin/deserialize_amount.rs +++ b/fuzz/fuzz_targets/bitcoin/deserialize_amount.rs @@ -36,7 +36,7 @@ fn main() { } } -#[cfg(test)] +#[cfg(all(test, fuzzing))] mod tests { fn extend_vec_from_hex(hex: &str, out: &mut Vec) { let mut b = 0; diff --git a/fuzz/fuzz_targets/bitcoin/deserialize_block.rs b/fuzz/fuzz_targets/bitcoin/deserialize_block.rs index 12ed6681..c70db2a1 100644 --- a/fuzz/fuzz_targets/bitcoin/deserialize_block.rs +++ b/fuzz/fuzz_targets/bitcoin/deserialize_block.rs @@ -13,7 +13,7 @@ fn main() { } } -#[cfg(test)] +#[cfg(all(test, fuzzing))] mod tests { fn extend_vec_from_hex(hex: &str, out: &mut Vec) { let mut b = 0; diff --git a/fuzz/fuzz_targets/bitcoin/deserialize_prefilled_transaction.rs b/fuzz/fuzz_targets/bitcoin/deserialize_prefilled_transaction.rs index 0bb3cec5..9e8ae790 100644 --- a/fuzz/fuzz_targets/bitcoin/deserialize_prefilled_transaction.rs +++ b/fuzz/fuzz_targets/bitcoin/deserialize_prefilled_transaction.rs @@ -22,7 +22,7 @@ fn main() { } } -#[cfg(test)] +#[cfg(all(test, fuzzing))] mod tests { fn extend_vec_from_hex(hex: &str, out: &mut Vec) { let mut b = 0; diff --git a/fuzz/fuzz_targets/bitcoin/deserialize_psbt.rs b/fuzz/fuzz_targets/bitcoin/deserialize_psbt.rs index a610138a..9ca46116 100644 --- a/fuzz/fuzz_targets/bitcoin/deserialize_psbt.rs +++ b/fuzz/fuzz_targets/bitcoin/deserialize_psbt.rs @@ -22,7 +22,7 @@ fn main() { } } -#[cfg(test)] +#[cfg(all(test, fuzzing))] mod tests { fn extend_vec_from_hex(hex: &str, out: &mut Vec) { let mut b = 0; diff --git a/fuzz/fuzz_targets/bitcoin/deserialize_script.rs b/fuzz/fuzz_targets/bitcoin/deserialize_script.rs index 5f00c812..1020e0b0 100644 --- a/fuzz/fuzz_targets/bitcoin/deserialize_script.rs +++ b/fuzz/fuzz_targets/bitcoin/deserialize_script.rs @@ -52,7 +52,7 @@ fn main() { } } -#[cfg(test)] +#[cfg(all(test, fuzzing))] mod tests { fn extend_vec_from_hex(hex: &str, out: &mut Vec) { let mut b = 0; diff --git a/fuzz/fuzz_targets/bitcoin/deserialize_transaction.rs b/fuzz/fuzz_targets/bitcoin/deserialize_transaction.rs index f11140fc..2a249b18 100644 --- a/fuzz/fuzz_targets/bitcoin/deserialize_transaction.rs +++ b/fuzz/fuzz_targets/bitcoin/deserialize_transaction.rs @@ -34,7 +34,7 @@ fn main() { } } -#[cfg(test)] +#[cfg(all(test, fuzzing))] mod tests { fn extend_vec_from_hex(hex: &str, out: &mut Vec) { let mut b = 0; diff --git a/fuzz/fuzz_targets/bitcoin/deserialize_witness.rs b/fuzz/fuzz_targets/bitcoin/deserialize_witness.rs index 3d8ef18e..940b7ff5 100644 --- a/fuzz/fuzz_targets/bitcoin/deserialize_witness.rs +++ b/fuzz/fuzz_targets/bitcoin/deserialize_witness.rs @@ -18,7 +18,7 @@ fn main() { } } -#[cfg(test)] +#[cfg(all(test, fuzzing))] mod tests { fn extend_vec_from_hex(hex: &str, out: &mut Vec) { let mut b = 0; diff --git a/fuzz/fuzz_targets/bitcoin/outpoint_string.rs b/fuzz/fuzz_targets/bitcoin/outpoint_string.rs index 208a4cc0..9130792b 100644 --- a/fuzz/fuzz_targets/bitcoin/outpoint_string.rs +++ b/fuzz/fuzz_targets/bitcoin/outpoint_string.rs @@ -49,7 +49,7 @@ fn main() { } } -#[cfg(test)] +#[cfg(all(test, fuzzing))] mod tests { fn extend_vec_from_hex(hex: &str, out: &mut Vec) { let mut b = 0; diff --git a/fuzz/fuzz_targets/bitcoin/script_bytes_to_asm_fmt.rs b/fuzz/fuzz_targets/bitcoin/script_bytes_to_asm_fmt.rs index 6d82af07..3e0bacc6 100644 --- a/fuzz/fuzz_targets/bitcoin/script_bytes_to_asm_fmt.rs +++ b/fuzz/fuzz_targets/bitcoin/script_bytes_to_asm_fmt.rs @@ -23,3 +23,30 @@ fn main() { }); } } + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00000", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/hashes/cbor.rs b/fuzz/fuzz_targets/hashes/cbor.rs index 59c04b4d..29287577 100644 --- a/fuzz/fuzz_targets/hashes/cbor.rs +++ b/fuzz/fuzz_targets/hashes/cbor.rs @@ -28,7 +28,7 @@ fn main() { } } -#[cfg(test)] +#[cfg(all(test, fuzzing))] mod tests { fn extend_vec_from_hex(hex: &str, out: &mut Vec) { let mut b = 0; diff --git a/fuzz/fuzz_targets/hashes/json.rs b/fuzz/fuzz_targets/hashes/json.rs index a7f9df69..2513f2e2 100644 --- a/fuzz/fuzz_targets/hashes/json.rs +++ b/fuzz/fuzz_targets/hashes/json.rs @@ -28,7 +28,7 @@ fn main() { } } -#[cfg(test)] +#[cfg(all(test, fuzzing))] mod tests { fn extend_vec_from_hex(hex: &str, out: &mut Vec) { let mut b = 0; diff --git a/fuzz/fuzz_targets/hashes/ripemd160.rs b/fuzz/fuzz_targets/hashes/ripemd160.rs index c6944d6c..0f6ad97b 100644 --- a/fuzz/fuzz_targets/hashes/ripemd160.rs +++ b/fuzz/fuzz_targets/hashes/ripemd160.rs @@ -20,7 +20,7 @@ fn main() { } } -#[cfg(test)] +#[cfg(all(test, fuzzing))] mod tests { fn extend_vec_from_hex(hex: &str, out: &mut Vec) { let mut b = 0; diff --git a/fuzz/fuzz_targets/hashes/sha1.rs b/fuzz/fuzz_targets/hashes/sha1.rs index 833a7880..531d8779 100644 --- a/fuzz/fuzz_targets/hashes/sha1.rs +++ b/fuzz/fuzz_targets/hashes/sha1.rs @@ -20,7 +20,7 @@ fn main() { } } -#[cfg(test)] +#[cfg(all(test, fuzzing))] mod tests { fn extend_vec_from_hex(hex: &str, out: &mut Vec) { let mut b = 0; diff --git a/fuzz/fuzz_targets/hashes/sha256.rs b/fuzz/fuzz_targets/hashes/sha256.rs index e893ce46..23456d19 100644 --- a/fuzz/fuzz_targets/hashes/sha256.rs +++ b/fuzz/fuzz_targets/hashes/sha256.rs @@ -20,7 +20,7 @@ fn main() { } } -#[cfg(test)] +#[cfg(all(test, fuzzing))] mod tests { fn extend_vec_from_hex(hex: &str, out: &mut Vec) { let mut b = 0; @@ -42,7 +42,7 @@ mod tests { #[test] fn duplicate_crash() { let mut a = Vec::new(); - extend_vec_from_hex("00000", &mut a); + extend_vec_from_hex("fff400610004", &mut a); super::do_test(&a); } } diff --git a/fuzz/fuzz_targets/hashes/sha512.rs b/fuzz/fuzz_targets/hashes/sha512.rs index 87b7f3a3..b2a9ad79 100644 --- a/fuzz/fuzz_targets/hashes/sha512.rs +++ b/fuzz/fuzz_targets/hashes/sha512.rs @@ -20,7 +20,7 @@ fn main() { } } -#[cfg(test)] +#[cfg(all(test, fuzzing))] mod tests { fn extend_vec_from_hex(hex: &str, out: &mut Vec) { let mut b = 0; diff --git a/fuzz/fuzz_targets/hashes/sha512_256.rs b/fuzz/fuzz_targets/hashes/sha512_256.rs index e99cb2f9..9a36dcfb 100644 --- a/fuzz/fuzz_targets/hashes/sha512_256.rs +++ b/fuzz/fuzz_targets/hashes/sha512_256.rs @@ -20,7 +20,7 @@ fn main() { } } -#[cfg(test)] +#[cfg(all(test, fuzzing))] mod tests { fn extend_vec_from_hex(hex: &str, out: &mut Vec) { let mut b = 0;