Skip to content

Commit b828208

Browse files
committed
Ensure Message always unwraps in fuzztarget
Hashes cant be all-0s, so we can normally unwrap, but fuzztarget can generate all-0 hashes, so we have to handle it and swap for something else.
1 parent f12d302 commit b828208

File tree

6 files changed

+48
-28
lines changed

6 files changed

+48
-28
lines changed

src/ln/channel.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use bitcoin_hashes::sha256::Hash as Sha256;
1111
use bitcoin_hashes::hash160::Hash as Hash160;
1212

1313
use secp256k1::key::{PublicKey,SecretKey};
14-
use secp256k1::{Secp256k1,Message,Signature};
14+
use secp256k1::{Secp256k1,Signature};
1515
use secp256k1;
1616

1717
use ln::msgs;
@@ -1061,7 +1061,7 @@ impl Channel {
10611061

10621062
let funding_redeemscript = self.get_funding_redeemscript();
10631063

1064-
let sighash = Message::from_slice(&bip143::SighashComponents::new(&tx).sighash_all(&tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]).unwrap();
1064+
let sighash = hash_to_message!(&bip143::SighashComponents::new(&tx).sighash_all(&tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]);
10651065
let our_sig = self.secp_ctx.sign(&sighash, &self.local_keys.funding_key);
10661066

10671067
tx.input[0].witness.push(Vec::new()); // First is the multisig dummy
@@ -1098,7 +1098,7 @@ impl Channel {
10981098
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &keys);
10991099

11001100
let our_htlc_key = secp_check!(chan_utils::derive_private_key(&self.secp_ctx, &keys.per_commitment_point, &self.local_keys.htlc_base_key), "Derived invalid key, peer is maliciously selecting parameters");
1101-
let sighash = Message::from_slice(&bip143::SighashComponents::new(&tx).sighash_all(&tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]).unwrap();
1101+
let sighash = hash_to_message!(&bip143::SighashComponents::new(&tx).sighash_all(&tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]);
11021102
let is_local_tx = PublicKey::from_secret_key(&self.secp_ctx, &our_htlc_key) == keys.a_htlc_key;
11031103
Ok((htlc_redeemscript, self.secp_ctx.sign(&sighash, &our_htlc_key), is_local_tx))
11041104
}
@@ -1402,7 +1402,7 @@ impl Channel {
14021402

14031403
let local_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?;
14041404
let mut local_initial_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, self.feerate_per_kw).0;
1405-
let local_sighash = Message::from_slice(&bip143::SighashComponents::new(&local_initial_commitment_tx).sighash_all(&local_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap();
1405+
let local_sighash = hash_to_message!(&bip143::SighashComponents::new(&local_initial_commitment_tx).sighash_all(&local_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]);
14061406

14071407
// They sign the "local" commitment transaction...
14081408
secp_check!(self.secp_ctx.verify(&local_sighash, &sig, &self.their_funding_pubkey.unwrap()), "Invalid funding_created signature from peer");
@@ -1412,7 +1412,7 @@ impl Channel {
14121412

14131413
let remote_keys = self.build_remote_transaction_keys()?;
14141414
let remote_initial_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, false, self.feerate_per_kw).0;
1415-
let remote_sighash = Message::from_slice(&bip143::SighashComponents::new(&remote_initial_commitment_tx).sighash_all(&remote_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap();
1415+
let remote_sighash = hash_to_message!(&bip143::SighashComponents::new(&remote_initial_commitment_tx).sighash_all(&remote_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]);
14161416

14171417
// We sign the "remote" commitment transaction, allowing them to broadcast the tx if they wish.
14181418
Ok((remote_initial_commitment_tx, local_initial_commitment_tx, self.secp_ctx.sign(&remote_sighash, &self.local_keys.funding_key), local_keys))
@@ -1481,7 +1481,7 @@ impl Channel {
14811481

14821482
let local_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?;
14831483
let mut local_initial_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, self.feerate_per_kw).0;
1484-
let local_sighash = Message::from_slice(&bip143::SighashComponents::new(&local_initial_commitment_tx).sighash_all(&local_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap();
1484+
let local_sighash = hash_to_message!(&bip143::SighashComponents::new(&local_initial_commitment_tx).sighash_all(&local_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]);
14851485

14861486
// They sign the "local" commitment transaction, allowing us to broadcast the tx if we wish.
14871487
secp_check!(self.secp_ctx.verify(&local_sighash, &msg.signature, &self.their_funding_pubkey.unwrap()), "Invalid funding_signed signature from peer");
@@ -1694,7 +1694,7 @@ impl Channel {
16941694
(commitment_tx.0, commitment_tx.1, htlcs_cloned)
16951695
};
16961696
let local_commitment_txid = local_commitment_tx.0.txid();
1697-
let local_sighash = Message::from_slice(&bip143::SighashComponents::new(&local_commitment_tx.0).sighash_all(&local_commitment_tx.0.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap();
1697+
let local_sighash = hash_to_message!(&bip143::SighashComponents::new(&local_commitment_tx.0).sighash_all(&local_commitment_tx.0.input[0], &funding_script, self.channel_value_satoshis)[..]);
16981698
secp_check!(self.secp_ctx.verify(&local_sighash, &msg.signature, &self.their_funding_pubkey.unwrap()), "Invalid commitment tx signature from peer");
16991699

17001700
//If channel fee was updated by funder confirm funder can afford the new fee rate when applied to the current local commitment transaction
@@ -1720,7 +1720,7 @@ impl Channel {
17201720
if let Some(_) = htlc.transaction_output_index {
17211721
let mut htlc_tx = self.build_htlc_transaction(&local_commitment_txid, &htlc, true, &local_keys, feerate_per_kw);
17221722
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &local_keys);
1723-
let htlc_sighash = Message::from_slice(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]).unwrap();
1723+
let htlc_sighash = hash_to_message!(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]);
17241724
secp_check!(self.secp_ctx.verify(&htlc_sighash, &msg.htlc_signatures[idx], &local_keys.b_htlc_key), "Invalid HTLC tx signature from peer");
17251725
let htlc_sig = if htlc.offered {
17261726
let htlc_sig = self.sign_htlc_transaction(&mut htlc_tx, &msg.htlc_signatures[idx], &None, &htlc, &local_keys)?;
@@ -2451,7 +2451,7 @@ impl Channel {
24512451

24522452
let (closing_tx, total_fee_satoshis) = self.build_closing_transaction(proposed_total_fee_satoshis, false);
24532453
let funding_redeemscript = self.get_funding_redeemscript();
2454-
let sighash = Message::from_slice(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]).unwrap();
2454+
let sighash = hash_to_message!(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]);
24552455

24562456
self.last_sent_closing_fee = Some((proposed_feerate, total_fee_satoshis));
24572457
Some(msgs::ClosingSigned {
@@ -2553,15 +2553,15 @@ impl Channel {
25532553
if used_total_fee != msg.fee_satoshis {
25542554
return Err(ChannelError::Close("Remote sent us a closing_signed with a fee greater than the value they can claim"));
25552555
}
2556-
let mut sighash = Message::from_slice(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]).unwrap();
2556+
let mut sighash = hash_to_message!(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]);
25572557

25582558
match self.secp_ctx.verify(&sighash, &msg.signature, &self.their_funding_pubkey.unwrap()) {
25592559
Ok(_) => {},
25602560
Err(_e) => {
25612561
// The remote end may have decided to revoke their output due to inconsistent dust
25622562
// limits, so check for that case by re-checking the signature here.
25632563
closing_tx = self.build_closing_transaction(msg.fee_satoshis, true).0;
2564-
sighash = Message::from_slice(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]).unwrap();
2564+
sighash = hash_to_message!(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]);
25652565
secp_check!(self.secp_ctx.verify(&sighash, &msg.signature, &self.their_funding_pubkey.unwrap()), "Invalid closing tx signature from peer");
25662566
},
25672567
};
@@ -2579,7 +2579,7 @@ impl Channel {
25792579
($new_feerate: expr) => {
25802580
let closing_tx_max_weight = Self::get_closing_transaction_weight(&self.get_closing_scriptpubkey(), self.their_shutdown_scriptpubkey.as_ref().unwrap());
25812581
let (closing_tx, used_total_fee) = self.build_closing_transaction($new_feerate * closing_tx_max_weight / 1000, false);
2582-
sighash = Message::from_slice(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]).unwrap();
2582+
sighash = hash_to_message!(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]);
25832583
let our_sig = self.secp_ctx.sign(&sighash, &self.local_keys.funding_key);
25842584
self.last_sent_closing_fee = Some(($new_feerate, used_total_fee));
25852585
return Ok((Some(msgs::ClosingSigned {
@@ -2988,7 +2988,7 @@ impl Channel {
29882988

29892989
let remote_keys = self.build_remote_transaction_keys()?;
29902990
let remote_initial_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, false, self.feerate_per_kw).0;
2991-
let remote_sighash = Message::from_slice(&bip143::SighashComponents::new(&remote_initial_commitment_tx).sighash_all(&remote_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap();
2991+
let remote_sighash = hash_to_message!(&bip143::SighashComponents::new(&remote_initial_commitment_tx).sighash_all(&remote_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]);
29922992

29932993
// We sign the "remote" commitment transaction, allowing them to broadcast the tx if they wish.
29942994
Ok((self.secp_ctx.sign(&remote_sighash, &self.local_keys.funding_key), remote_initial_commitment_tx))
@@ -3075,7 +3075,7 @@ impl Channel {
30753075
excess_data: Vec::new(),
30763076
};
30773077

3078-
let msghash = Message::from_slice(&Sha256dHash::from_data(&msg.encode()[..])[..]).unwrap();
3078+
let msghash = hash_to_message!(&Sha256dHash::from_data(&msg.encode()[..])[..]);
30793079
let sig = self.secp_ctx.sign(&msghash, &self.local_keys.funding_key);
30803080

30813081
Ok((msg, sig))
@@ -3290,15 +3290,15 @@ impl Channel {
32903290
let remote_keys = self.build_remote_transaction_keys()?;
32913291
let remote_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, true, feerate_per_kw);
32923292
let remote_commitment_txid = remote_commitment_tx.0.txid();
3293-
let remote_sighash = Message::from_slice(&bip143::SighashComponents::new(&remote_commitment_tx.0).sighash_all(&remote_commitment_tx.0.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap();
3293+
let remote_sighash = hash_to_message!(&bip143::SighashComponents::new(&remote_commitment_tx.0).sighash_all(&remote_commitment_tx.0.input[0], &funding_script, self.channel_value_satoshis)[..]);
32943294
let our_sig = self.secp_ctx.sign(&remote_sighash, &self.local_keys.funding_key);
32953295

32963296
let mut htlc_sigs = Vec::with_capacity(remote_commitment_tx.1);
32973297
for &(ref htlc, _) in remote_commitment_tx.2.iter() {
32983298
if let Some(_) = htlc.transaction_output_index {
32993299
let htlc_tx = self.build_htlc_transaction(&remote_commitment_txid, htlc, false, &remote_keys, feerate_per_kw);
33003300
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &remote_keys);
3301-
let htlc_sighash = Message::from_slice(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]).unwrap();
3301+
let htlc_sighash = hash_to_message!(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]);
33023302
let our_htlc_key = secp_check!(chan_utils::derive_private_key(&self.secp_ctx, &remote_keys.per_commitment_point, &self.local_keys.htlc_base_key), "Derived invalid key, peer is maliciously selecting parameters");
33033303
htlc_sigs.push(self.secp_ctx.sign(&htlc_sighash, &our_htlc_key));
33043304
}

src/ln/channelmanager.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use bitcoin_hashes::sha256::Hash as Sha256;
2020
use bitcoin_hashes::cmp::fixed_time_eq;
2121

2222
use secp256k1::key::{SecretKey,PublicKey};
23-
use secp256k1::{Secp256k1,Message};
23+
use secp256k1::Secp256k1;
2424
use secp256k1::ecdh::SharedSecret;
2525
use secp256k1;
2626

@@ -937,7 +937,7 @@ impl ChannelManager {
937937
};
938938

939939
let msg_hash = Sha256dHash::from_data(&unsigned.encode()[..]);
940-
let sig = self.secp_ctx.sign(&Message::from_slice(&msg_hash[..]).unwrap(), &self.our_network_key);
940+
let sig = self.secp_ctx.sign(&hash_to_message!(&msg_hash[..]), &self.our_network_key);
941941

942942
Ok(msgs::ChannelUpdate {
943943
signature: sig,
@@ -1130,7 +1130,7 @@ impl ChannelManager {
11301130
Ok(res) => res,
11311131
Err(_) => return None, // Only in case of state precondition violations eg channel is closing
11321132
};
1133-
let msghash = Message::from_slice(&Sha256dHash::from_data(&announcement.encode()[..])[..]).unwrap();
1133+
let msghash = hash_to_message!(&Sha256dHash::from_data(&announcement.encode()[..])[..]);
11341134
let our_node_sig = self.secp_ctx.sign(&msghash, &self.our_network_key);
11351135

11361136
Some(msgs::AnnouncementSignatures {
@@ -2101,7 +2101,7 @@ impl ChannelManager {
21012101
try_chan_entry!(self, chan.get_mut().get_channel_announcement(our_node_id.clone(), self.genesis_hash.clone()), channel_state, chan);
21022102

21032103
let were_node_one = announcement.node_id_1 == our_node_id;
2104-
let msghash = Message::from_slice(&Sha256dHash::from_data(&announcement.encode()[..])[..]).unwrap();
2104+
let msghash = hash_to_message!(&Sha256dHash::from_data(&announcement.encode()[..])[..]);
21052105
if self.secp_ctx.verify(&msghash, &msg.node_signature, if were_node_one { &announcement.node_id_2 } else { &announcement.node_id_1 }).is_err() ||
21062106
self.secp_ctx.verify(&msghash, &msg.bitcoin_signature, if were_node_one { &announcement.bitcoin_key_2 } else { &announcement.bitcoin_key_1 }).is_err() {
21072107
try_chan_entry!(self, Err(ChannelError::Close("Bad announcement_signatures node_signature")), channel_state, chan);

src/ln/channelmonitor.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use bitcoin_hashes::Hash;
2424
use bitcoin_hashes::sha256::Hash as Sha256;
2525
use bitcoin_hashes::hash160::Hash as Hash160;
2626

27-
use secp256k1::{Secp256k1,Message,Signature};
27+
use secp256k1::{Secp256k1,Signature};
2828
use secp256k1::key::{SecretKey,PublicKey};
2929
use secp256k1;
3030

@@ -1105,7 +1105,7 @@ impl ChannelMonitor {
11051105
let htlc = &per_commitment_option.unwrap()[$htlc_idx.unwrap()].0;
11061106
chan_utils::get_htlc_redeemscript_with_explicit_keys(htlc, &a_htlc_key, &b_htlc_key, &revocation_pubkey)
11071107
};
1108-
let sighash = ignore_error!(Message::from_slice(&$sighash_parts.sighash_all(&$input, &redeemscript, $amount)[..]));
1108+
let sighash = hash_to_message!(&$sighash_parts.sighash_all(&$input, &redeemscript, $amount)[..]);
11091109
let revocation_key = ignore_error!(chan_utils::derive_private_revocation_key(&self.secp_ctx, &per_commitment_key, &revocation_base_key));
11101110
(self.secp_ctx.sign(&sighash, &revocation_key), redeemscript)
11111111
},
@@ -1327,7 +1327,7 @@ impl ChannelMonitor {
13271327
Storage::Local { ref htlc_base_key, .. } => {
13281328
let htlc = &per_commitment_option.unwrap()[$input.sequence as usize].0;
13291329
let redeemscript = chan_utils::get_htlc_redeemscript_with_explicit_keys(htlc, &a_htlc_key, &b_htlc_key, &revocation_pubkey);
1330-
let sighash = ignore_error!(Message::from_slice(&$sighash_parts.sighash_all(&$input, &redeemscript, $amount)[..]));
1330+
let sighash = hash_to_message!(&$sighash_parts.sighash_all(&$input, &redeemscript, $amount)[..]);
13311331
let htlc_key = ignore_error!(chan_utils::derive_private_key(&self.secp_ctx, revocation_point, &htlc_base_key));
13321332
(self.secp_ctx.sign(&sighash, &htlc_key), redeemscript)
13331333
},
@@ -1512,7 +1512,7 @@ impl ChannelMonitor {
15121512

15131513
let sig = match self.key_storage {
15141514
Storage::Local { ref revocation_base_key, .. } => {
1515-
let sighash = ignore_error!(Message::from_slice(&sighash_parts.sighash_all(&spend_tx.input[0], &redeemscript, amount)[..]));
1515+
let sighash = hash_to_message!(&sighash_parts.sighash_all(&spend_tx.input[0], &redeemscript, amount)[..]);
15161516
let revocation_key = ignore_error!(chan_utils::derive_private_revocation_key(&self.secp_ctx, &per_commitment_key, &revocation_base_key));
15171517
self.secp_ctx.sign(&sighash, &revocation_key)
15181518
}

src/ln/router.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//! interrogate it to get routes for your own payments.
55
66
use secp256k1::key::PublicKey;
7-
use secp256k1::{Secp256k1,Message};
7+
use secp256k1::Secp256k1;
88
use secp256k1;
99

1010
use bitcoin::util::hash::Sha256dHash;
@@ -239,7 +239,7 @@ macro_rules! secp_verify_sig {
239239

240240
impl RoutingMessageHandler for Router {
241241
fn handle_node_announcement(&self, msg: &msgs::NodeAnnouncement) -> Result<bool, HandleError> {
242-
let msg_hash = Message::from_slice(&Sha256dHash::from_data(&msg.contents.encode()[..])[..]).unwrap();
242+
let msg_hash = hash_to_message!(&Sha256dHash::from_data(&msg.contents.encode()[..])[..]);
243243
secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.signature, &msg.contents.node_id);
244244

245245
if msg.contents.features.requires_unknown_bits() {
@@ -272,7 +272,7 @@ impl RoutingMessageHandler for Router {
272272
return Err(HandleError{err: "Channel announcement node had a channel with itself", action: Some(ErrorAction::IgnoreError)});
273273
}
274274

275-
let msg_hash = Message::from_slice(&Sha256dHash::from_data(&msg.contents.encode()[..])[..]).unwrap();
275+
let msg_hash = hash_to_message!(&Sha256dHash::from_data(&msg.contents.encode()[..])[..]);
276276
secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.node_signature_1, &msg.contents.node_id_1);
277277
secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.node_signature_2, &msg.contents.node_id_2);
278278
secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.bitcoin_signature_1, &msg.contents.bitcoin_key_1);
@@ -448,7 +448,7 @@ impl RoutingMessageHandler for Router {
448448
};
449449
}
450450
}
451-
let msg_hash = Message::from_slice(&Sha256dHash::from_data(&msg.contents.encode()[..])[..]).unwrap();
451+
let msg_hash = hash_to_message!(&Sha256dHash::from_data(&msg.contents.encode()[..])[..]);
452452
if msg.contents.flags & 1 == 1 {
453453
dest_node_id = channel.one_to_two.src_node_id.clone();
454454
secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.signature, &channel.two_to_one.src_node_id);

src/util/fuzz_wrappers.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
macro_rules! hash_to_message {
2+
($slice: expr) => {
3+
{
4+
#[cfg(not(feature = "fuzztarget"))]
5+
{
6+
::secp256k1::Message::from_slice($slice).unwrap()
7+
}
8+
#[cfg(feature = "fuzztarget")]
9+
{
10+
match ::secp256k1::Message::from_slice($slice) {
11+
Ok(msg) => msg,
12+
Err(_) => ::secp256k1::Message::from_slice(&[1; 32]).unwrap()
13+
}
14+
}
15+
}
16+
}
17+
}

src/util/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,6 @@ pub use self::rng::{reset_rng_state, fill_bytes};
2727

2828
#[cfg(test)]
2929
pub(crate) mod test_utils;
30+
31+
#[macro_use]
32+
pub(crate) mod fuzz_wrappers;

0 commit comments

Comments
 (0)