79 lines
2.4 KiB
Rust
79 lines
2.4 KiB
Rust
#![no_main]
|
|
|
|
use libfuzzer_sys::fuzz_target;
|
|
|
|
use liana::{descriptors::LianaDescriptor, miniscript::bitcoin::Network};
|
|
use secp256k1::global::SECP256K1;
|
|
|
|
use std::str::{self, FromStr};
|
|
|
|
// Hacky way to detect too deeply nested wrappers, which would make rust-miniscript stack overflow
|
|
// when parsing them.
|
|
fn too_deep_wrappers(desc_str: &str) -> bool {
|
|
let mut wrapper_count = 0;
|
|
for c in desc_str.chars() {
|
|
if c == ':' || c == '(' || c == ')' || c == ',' {
|
|
if c == ':' && wrapper_count > 10 {
|
|
return true;
|
|
}
|
|
wrapper_count = 0;
|
|
} else {
|
|
wrapper_count += 1;
|
|
}
|
|
}
|
|
false
|
|
}
|
|
|
|
fuzz_target!(|data: &[u8]| {
|
|
let desc_str = match str::from_utf8(data) {
|
|
Ok(s) => s,
|
|
Err(_) => return,
|
|
};
|
|
if data.len() > 10_000 {
|
|
return;
|
|
}
|
|
|
|
// Rust-miniscript uses a recursive parsing algorithm which could make us crash when trying to
|
|
// parse nested fragments. Until they fix it, rule out the most trivial recursion overflow the
|
|
// fuzzer can generate: too deep wrappers.
|
|
// FIXME: this shouldn't be necessary when upgrading to the next rust-miniscript version.
|
|
if too_deep_wrappers(&desc_str) {
|
|
return;
|
|
}
|
|
|
|
let desc = match LianaDescriptor::from_str(desc_str) {
|
|
Ok(d) => d,
|
|
Err(_) => return,
|
|
};
|
|
|
|
// The descriptor must roundtrip.
|
|
assert_eq!(desc, LianaDescriptor::from_str(&desc.to_string()).unwrap());
|
|
|
|
// We can get the policy out of this desc and a desc out of this policy, but it's not
|
|
// guaranteed to roundtrip: policy->descriptor involves a compilation.
|
|
LianaDescriptor::new(desc.policy());
|
|
|
|
// Exercise the various methods on the descriptor. None should crash.
|
|
desc.receive_descriptor();
|
|
desc.change_descriptor();
|
|
desc.first_timelock_value();
|
|
desc.max_sat_weight();
|
|
desc.max_sat_vbytes();
|
|
desc.spender_input_size();
|
|
|
|
// Exercise the various methods of derived descriptors. None should crash.
|
|
let der_index = 42.into();
|
|
let der_descs = [
|
|
desc.receive_descriptor().derive(der_index, &SECP256K1),
|
|
desc.change_descriptor().derive(der_index, &SECP256K1),
|
|
];
|
|
let mut psbt_in = Default::default();
|
|
let mut psbt_out = Default::default();
|
|
for desc in der_descs {
|
|
desc.address(Network::Bitcoin);
|
|
desc.script_pubkey();
|
|
desc.update_psbt_in(&mut psbt_in);
|
|
desc.update_change_psbt_out(&mut psbt_out);
|
|
}
|
|
});
|