diff --git a/fuzz/fuzz_targets/bitcoin/deserialize_psbt.rs b/fuzz/fuzz_targets/bitcoin/deserialize_psbt.rs index 59d28142c..b3fe54bbd 100644 --- a/fuzz/fuzz_targets/bitcoin/deserialize_psbt.rs +++ b/fuzz/fuzz_targets/bitcoin/deserialize_psbt.rs @@ -1,16 +1,7 @@ use honggfuzz::fuzz; -fn consume_random_bytes<'a>(data: &mut &'a [u8]) -> &'a [u8] { - if data.is_empty() { - return &[]; - } - - let length = (data[0] as usize) % (data.len() + 1); - let (bytes, rest) = data.split_at(length); - *data = rest; - - bytes -} +mod fuzz_utils; +use fuzz_utils::consume_random_bytes; fn do_test(data: &[u8]) { let mut new_data = data; diff --git a/fuzz/fuzz_targets/bitcoin/deserialize_script.rs b/fuzz/fuzz_targets/bitcoin/deserialize_script.rs index 6943bc64c..e7c1191b4 100644 --- a/fuzz/fuzz_targets/bitcoin/deserialize_script.rs +++ b/fuzz/fuzz_targets/bitcoin/deserialize_script.rs @@ -1,15 +1,27 @@ use bitcoin::address::Address; use bitcoin::consensus::encode; use bitcoin::script::{self, ScriptExt as _}; -use bitcoin::Network; +use bitcoin::{FeeRate, Network}; use honggfuzz::fuzz; +mod fuzz_utils; +use fuzz_utils::{consume_random_bytes, consume_u64}; + fn do_test(data: &[u8]) { - let s: Result = encode::deserialize(data); + let mut new_data = data; + let bytes = consume_random_bytes(&mut new_data); + let s: Result = encode::deserialize(bytes); if let Ok(script) = s { let _: Result, script::Error> = script.instructions().collect(); let _ = script.to_string(); + let _ = script.count_sigops(); + let _ = script.count_sigops_legacy(); + let _ = script.minimal_non_dust(); + + let fee_rate = FeeRate::from_sat_per_kwu(consume_u64(&mut new_data)); + let _ = script.minimal_non_dust_custom(fee_rate); + let mut b = script::Builder::new(); for ins in script.instructions_minimal() { if ins.is_err() { diff --git a/fuzz/fuzz_targets/bitcoin/fuzz_utils.rs b/fuzz/fuzz_targets/bitcoin/fuzz_utils.rs new file mode 100644 index 000000000..aeaa11ae2 --- /dev/null +++ b/fuzz/fuzz_targets/bitcoin/fuzz_utils.rs @@ -0,0 +1,33 @@ +pub fn consume_random_bytes<'a>(data: &mut &'a [u8]) -> &'a [u8] { + if data.is_empty() { + return &[]; + } + + let length = (data[0] as usize) % (data.len() + 1); + let (bytes, rest) = data.split_at(length); + *data = rest; + + bytes +} + +#[allow(dead_code)] +pub fn consume_u64(data: &mut &[u8]) -> u64 { + // We need at least 8 bytes to read a u64 + if data.len() < 8 { + return 0; + } + + let (u64_bytes, rest) = data.split_at(8); + *data = rest; + + u64::from_le_bytes([ + u64_bytes[0], + u64_bytes[1], + u64_bytes[2], + u64_bytes[3], + u64_bytes[4], + u64_bytes[5], + u64_bytes[6], + u64_bytes[7], + ]) +}