diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index d698a68c..92b61597 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -10,7 +10,7 @@ jobs: strategy: fail-fast: false matrix: - fuzz_target: [deser_net_msg, deserialize_address, deserialize_amount, deserialize_block, deserialize_psbt, deserialize_script, deserialize_transaction, deserialize_witness, outpoint_string, uint128_fuzz, script_bytes_to_asm_fmt] + fuzz_target: [deser_net_msg, deserialize_address, deserialize_amount, deserialize_block, deserialize_psbt, deserialize_script, deserialize_transaction, deserialize_prefilled_transaction, deserialize_witness, outpoint_string, uint128_fuzz, script_bytes_to_asm_fmt] steps: - name: Install test dependencies run: sudo apt-get update -y && sudo apt-get install -y binutils-dev libunwind8-dev libcurl4-openssl-dev libelf-dev libdw-dev cmake gcc libiberty-dev diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 555ec383..ae61cee3 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -32,6 +32,10 @@ path = "fuzz_targets/deserialize_script.rs" name = "deserialize_transaction" path = "fuzz_targets/deserialize_transaction.rs" +[[bin]] +name = "deserialize_prefilled_transaction" +path = "fuzz_targets/deserialize_prefilled_transaction.rs" + [[bin]] name = "deserialize_address" path = "fuzz_targets/deserialize_address.rs" diff --git a/fuzz/fuzz_targets/deserialize_prefilled_transaction.rs b/fuzz/fuzz_targets/deserialize_prefilled_transaction.rs new file mode 100644 index 00000000..1da8ec48 --- /dev/null +++ b/fuzz/fuzz_targets/deserialize_prefilled_transaction.rs @@ -0,0 +1,61 @@ +extern crate bitcoin; + +fn do_test(data: &[u8]) { + // We already fuzz Transactions in `./deserialize_transaction.rs`. + let tx_result: Result = bitcoin::consensus::encode::deserialize(data); + + match tx_result { + Err(_) => {}, + Ok(mut tx) => { + let ser = bitcoin::consensus::encode::serialize(&tx); + assert_eq!(&ser[..], data); + } + } +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(&data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(test)] +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("00000000", &mut a); + super::do_test(&a); + } +}