Merge rust-bitcoin/rust-bitcoin#4185: fuzz: cover more stuff for Script

08e0d4f0e5 fuzz: cover minimal_non_dust_custom  for Script (Bruno Garcia)
66fee1ef87 fuzz: add consume_u64 (Bruno Garcia)
35e7027a08 fuzz: move consume_random_bytes to a util file (Bruno Garcia)
eb8ecd5e3c fuzz: cover minimal_non_dust for Script (Bruno Garcia)
cab8a6134f fuzz: cover count_sigops{_legacy} for Script (Bruno Garcia)

Pull request description:

  This PR adds fuzz coverage for `count_sigops`, `count_sigops_legacy`, `minimal_non_dust` and `minimal_non_dust_custom`. In order to not duplicate `consume_random_bytes`, it moves it to a util file and adds a `consume_u64` function to be used in the `deserialize_script` target to fuzz `minimal_non_dust_custom`.

ACKs for top commit:
  apoelstra:
    ACK 08e0d4f0e53d97edd655ec1103d60a2b4715fb91; successfully ran local tests

Tree-SHA512: d9b0b94af3e2c1b06b790e0b7d13095493d372f8c22babb9139f25f45ff580020a04c00bdba023bf4f89e2db1e13ffdff8e43f073516e7699c2ccc0233b0eb4b
This commit is contained in:
merge-script 2025-03-05 14:46:45 +00:00
commit 16860fefd2
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
3 changed files with 49 additions and 13 deletions

View File

@ -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;

View File

@ -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<script::ScriptBuf, _> = encode::deserialize(data);
let mut new_data = data;
let bytes = consume_random_bytes(&mut new_data);
let s: Result<script::ScriptBuf, _> = encode::deserialize(bytes);
if let Ok(script) = s {
let _: Result<Vec<script::Instruction>, 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() {

View File

@ -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],
])
}