Skip to content

Commit fa889fc

Browse files
Antoine RiardTheBlueMatt
Antoine Riard
authored andcommitted
Implement ErrorMessage msg and ErrorAction::SendErrorMessage + fuzz test
1 parent fa9715d commit fa889fc

File tree

5 files changed

+98
-1
lines changed

5 files changed

+98
-1
lines changed

fuzz/fuzz_targets/channel_target.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ pub fn do_test(data: &[u8]) {
118118
msgs::DecodeError::UnknownRealmByte => return,
119119
msgs::DecodeError::BadPublicKey => return,
120120
msgs::DecodeError::BadSignature => return,
121+
msgs::DecodeError::BadText => return,
121122
msgs::DecodeError::ExtraAddressesPerType => return,
122123
msgs::DecodeError::WrongLength => panic!("We picked the length..."),
123124
}
@@ -138,6 +139,7 @@ pub fn do_test(data: &[u8]) {
138139
msgs::DecodeError::UnknownRealmByte => return,
139140
msgs::DecodeError::BadPublicKey => return,
140141
msgs::DecodeError::BadSignature => return,
142+
msgs::DecodeError::BadText => return,
141143
msgs::DecodeError::ExtraAddressesPerType => return,
142144
msgs::DecodeError::WrongLength => panic!("We picked the length..."),
143145
}

fuzz/fuzz_targets/msg_targets/gen_target.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
for target in CommitmentSigned FundingCreated FundingLocked FundingSigned OpenChannel RevokeAndACK Shutdown UpdateAddHTLC UpdateFailHTLC UpdateFailMalformedHTLC UpdateFee UpdateFulfillHTLC AcceptChannel ClosingSigned ChannelReestablish; do
1+
for target in CommitmentSigned FundingCreated FundingLocked FundingSigned OpenChannel RevokeAndACK Shutdown UpdateAddHTLC UpdateFailHTLC UpdateFailMalformedHTLC UpdateFee UpdateFulfillHTLC AcceptChannel ClosingSigned ChannelReestablish ErrorMessage; do
22
tn=$(echo $target | sed 's/\([a-z0-9]\)\([A-Z]\)/\1_\2/g')
33
fn=msg_$(echo $tn | tr '[:upper:]' '[:lower:]')_target.rs
44
cat msg_target_template.txt | sed s/MSG_TARGET/$target/ > $fn
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// This file is auto-generated by gen_target.sh based on msg_target_template.txt
2+
// To modify it, modify msg_target_template.txt and run gen_target.sh instead.
3+
4+
extern crate lightning;
5+
6+
use lightning::ln::msgs;
7+
use lightning::util::reset_rng_state;
8+
9+
use lightning::ln::msgs::{MsgEncodable, MsgDecodable};
10+
11+
mod utils;
12+
13+
#[inline]
14+
pub fn do_test(data: &[u8]) {
15+
reset_rng_state();
16+
test_msg!(msgs::ErrorMessage, data);
17+
}
18+
19+
#[cfg(feature = "afl")]
20+
extern crate afl;
21+
#[cfg(feature = "afl")]
22+
fn main() {
23+
afl::read_stdio_bytes(|data| {
24+
do_test(&data);
25+
});
26+
}
27+
28+
#[cfg(feature = "honggfuzz")]
29+
#[macro_use] extern crate honggfuzz;
30+
#[cfg(feature = "honggfuzz")]
31+
fn main() {
32+
loop {
33+
fuzz!(|data| {
34+
do_test(data);
35+
});
36+
}
37+
}
38+
39+
#[cfg(test)]
40+
mod tests {
41+
use utils::extend_vec_from_hex;
42+
#[test]
43+
fn duplicate_crash() {
44+
let mut a = Vec::new();
45+
extend_vec_from_hex("00", &mut a);
46+
super::do_test(&a);
47+
}
48+
}

src/ln/msgs.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ pub enum DecodeError {
3131
BadPublicKey,
3232
/// Failed to decode a signature (ie it's invalid)
3333
BadSignature,
34+
/// Value expected to be text wasn't decodable as text
35+
BadText,
3436
/// Buffer not of right length (either too short or too long)
3537
WrongLength,
3638
/// node_announcement included more than one address of a given type!
@@ -138,6 +140,11 @@ pub struct Init {
138140
pub local_features: LocalFeatures,
139141
}
140142

143+
pub struct ErrorMessage {
144+
pub channel_id: [u8; 32],
145+
pub data: String,
146+
}
147+
141148
pub struct Ping {
142149
pub ponglen: u16,
143150
pub byteslen: u16,
@@ -375,6 +382,10 @@ pub enum ErrorAction {
375382
DisconnectPeer,
376383
/// The peer did something harmless that we weren't able to process, just log and ignore
377384
IgnoreError,
385+
/// The peer did something incorrect. Tell them.
386+
SendErrorMessage {
387+
msg: ErrorMessage
388+
},
378389
}
379390

380391
pub struct HandleError { //TODO: rename me
@@ -486,6 +497,7 @@ impl Error for DecodeError {
486497
DecodeError::UnknownRealmByte => "Unknown realm byte in Onion packet",
487498
DecodeError::BadPublicKey => "Invalid public key in packet",
488499
DecodeError::BadSignature => "Invalid signature in packet",
500+
DecodeError::BadText => "Invalid text in packet",
489501
DecodeError::WrongLength => "Data was wrong length for packet",
490502
DecodeError::ExtraAddressesPerType => "More than one address of a single type",
491503
}
@@ -1600,6 +1612,37 @@ impl MsgEncodable for OnionErrorPacket {
16001612
}
16011613
}
16021614

1615+
impl MsgEncodable for ErrorMessage {
1616+
fn encode(&self) -> Vec<u8> {
1617+
let mut res = Vec::with_capacity(34 + self.data.len());
1618+
res.extend_from_slice(&self.channel_id);
1619+
res.extend_from_slice(&byte_utils::be16_to_array(self.data.len() as u16));
1620+
res.extend_from_slice(&self.data.as_bytes());
1621+
res
1622+
}
1623+
}
1624+
impl MsgDecodable for ErrorMessage {
1625+
fn decode(v: &[u8]) -> Result<Self,DecodeError> {
1626+
if v.len() < 34 {
1627+
return Err(DecodeError::WrongLength);
1628+
}
1629+
let len = byte_utils::slice_to_be16(&v[32..34]);
1630+
if v.len() < 34 + len as usize {
1631+
return Err(DecodeError::WrongLength);
1632+
}
1633+
let data = match String::from_utf8(v[34..34 + len as usize].to_vec()) {
1634+
Ok(s) => s,
1635+
Err(_) => return Err(DecodeError::BadText),
1636+
};
1637+
let mut channel_id = [0; 32];
1638+
channel_id[..].copy_from_slice(&v[0..32]);
1639+
Ok(Self {
1640+
channel_id,
1641+
data,
1642+
})
1643+
}
1644+
}
1645+
16031646
#[cfg(test)]
16041647
mod tests {
16051648
use bitcoin::util::misc::hex_bytes;

src/ln/peer_handler.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,10 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
302302
msgs::ErrorAction::IgnoreError => {
303303
continue;
304304
},
305+
msgs::ErrorAction::SendErrorMessage { msg } => {
306+
encode_and_send_msg!(msg, 17);
307+
continue;
308+
},
305309
}
306310
} else {
307311
return Err(PeerHandleError{ no_connection_possible: false });

0 commit comments

Comments
 (0)