Skip to content

Commit 6f96d02

Browse files
Require length limited reader for LN gossip messages
Continuing the work of the last few commits, here we require that some LN gossip messages be read from a length limiting reader. The messages' updates are separated into their own commit because they definitely should use a length limited reader but they also require breaking out of the ser macros. We can't use the macros because each message contains a non-TLV field that will always consume the rest of the reader, while the ser macros only support reading non-TLV fields that know when to stop reading.
1 parent 50745bf commit 6f96d02

File tree

6 files changed

+82
-36
lines changed

6 files changed

+82
-36
lines changed

fuzz/src/msg_targets/utils.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,13 @@ macro_rules! test_msg_simple {
7171
#[macro_export]
7272
macro_rules! test_msg_exact {
7373
($MsgType: path, $data: ident) => {{
74-
use lightning::util::ser::{Readable, Writeable};
75-
let mut r = ::lightning::io::Cursor::new($data);
76-
if let Ok(msg) = <$MsgType as Readable>::read(&mut r) {
74+
use lightning::util::ser::{LengthReadable, Writeable};
75+
if let Ok(msg) =
76+
<$MsgType as LengthReadable>::read_from_fixed_length_buffer(&mut &$data[..])
77+
{
7778
let mut w = VecWriter(Vec::new());
7879
msg.write(&mut w).unwrap();
79-
assert_eq!(&r.into_inner()[..], &w.0[..]);
80+
assert_eq!(&$data[..], &w.0[..]);
8081
assert_eq!(msg.serialized_length(), w.0.len());
8182
}
8283
}};

fuzz/src/router.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use lightning::routing::utxo::{UtxoFuture, UtxoLookup, UtxoLookupError, UtxoResu
3030
use lightning::types::features::{BlindedHopFeatures, Bolt12InvoiceFeatures};
3131
use lightning::util::config::UserConfig;
3232
use lightning::util::hash_tables::*;
33-
use lightning::util::ser::Readable;
33+
use lightning::util::ser::LengthReadable;
3434

3535
use bitcoin::hashes::Hash;
3636
use bitcoin::network::Network;
@@ -146,10 +146,11 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
146146

147147
macro_rules! decode_msg {
148148
($MsgType: path, $len: expr) => {{
149-
let mut reader = ::lightning::io::Cursor::new(get_slice!($len));
150-
match <$MsgType>::read(&mut reader) {
149+
let data = get_slice!($len);
150+
let mut reader = &data[..];
151+
match <$MsgType>::read_from_fixed_length_buffer(&mut reader) {
151152
Ok(msg) => {
152-
assert_eq!(reader.position(), $len as u64);
153+
assert_eq!(reader.len(), $len);
153154
msg
154155
},
155156
Err(e) => match e {

lightning/src/ln/msgs.rs

+60-21
Original file line numberDiff line numberDiff line change
@@ -3572,8 +3572,8 @@ impl Writeable for UnsignedChannelAnnouncement {
35723572
}
35733573
}
35743574

3575-
impl Readable for UnsignedChannelAnnouncement {
3576-
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
3575+
impl LengthReadable for UnsignedChannelAnnouncement {
3576+
fn read_from_fixed_length_buffer<R: LengthLimitedRead>(r: &mut R) -> Result<Self, DecodeError> {
35773577
Ok(Self {
35783578
features: Readable::read(r)?,
35793579
chain_hash: Readable::read(r)?,
@@ -3587,13 +3587,28 @@ impl Readable for UnsignedChannelAnnouncement {
35873587
}
35883588
}
35893589

3590-
impl_writeable!(ChannelAnnouncement, {
3591-
node_signature_1,
3592-
node_signature_2,
3593-
bitcoin_signature_1,
3594-
bitcoin_signature_2,
3595-
contents
3596-
});
3590+
impl Writeable for ChannelAnnouncement {
3591+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
3592+
self.node_signature_1.write(w)?;
3593+
self.node_signature_2.write(w)?;
3594+
self.bitcoin_signature_1.write(w)?;
3595+
self.bitcoin_signature_2.write(w)?;
3596+
self.contents.write(w)?;
3597+
Ok(())
3598+
}
3599+
}
3600+
3601+
impl LengthReadable for ChannelAnnouncement {
3602+
fn read_from_fixed_length_buffer<R: LengthLimitedRead>(r: &mut R) -> Result<Self, DecodeError> {
3603+
Ok(Self {
3604+
node_signature_1: Readable::read(r)?,
3605+
node_signature_2: Readable::read(r)?,
3606+
bitcoin_signature_1: Readable::read(r)?,
3607+
bitcoin_signature_2: Readable::read(r)?,
3608+
contents: LengthReadable::read_from_fixed_length_buffer(r)?,
3609+
})
3610+
}
3611+
}
35973612

35983613
impl Writeable for UnsignedChannelUpdate {
35993614
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
@@ -3614,8 +3629,8 @@ impl Writeable for UnsignedChannelUpdate {
36143629
}
36153630
}
36163631

3617-
impl Readable for UnsignedChannelUpdate {
3618-
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
3632+
impl LengthReadable for UnsignedChannelUpdate {
3633+
fn read_from_fixed_length_buffer<R: LengthLimitedRead>(r: &mut R) -> Result<Self, DecodeError> {
36193634
let res = Self {
36203635
chain_hash: Readable::read(r)?,
36213636
short_channel_id: Readable::read(r)?,
@@ -3639,10 +3654,22 @@ impl Readable for UnsignedChannelUpdate {
36393654
}
36403655
}
36413656

3642-
impl_writeable!(ChannelUpdate, {
3643-
signature,
3644-
contents
3645-
});
3657+
impl Writeable for ChannelUpdate {
3658+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
3659+
self.signature.write(w)?;
3660+
self.contents.write(w)?;
3661+
Ok(())
3662+
}
3663+
}
3664+
3665+
impl LengthReadable for ChannelUpdate {
3666+
fn read_from_fixed_length_buffer<R: LengthLimitedRead>(r: &mut R) -> Result<Self, DecodeError> {
3667+
Ok(Self {
3668+
signature: Readable::read(r)?,
3669+
contents: LengthReadable::read_from_fixed_length_buffer(r)?,
3670+
})
3671+
}
3672+
}
36463673

36473674
impl Writeable for ErrorMessage {
36483675
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
@@ -3720,8 +3747,8 @@ impl Writeable for UnsignedNodeAnnouncement {
37203747
}
37213748
}
37223749

3723-
impl Readable for UnsignedNodeAnnouncement {
3724-
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
3750+
impl LengthReadable for UnsignedNodeAnnouncement {
3751+
fn read_from_fixed_length_buffer<R: LengthLimitedRead>(r: &mut R) -> Result<Self, DecodeError> {
37253752
let features: NodeFeatures = Readable::read(r)?;
37263753
let timestamp: u32 = Readable::read(r)?;
37273754
let node_id: NodeId = Readable::read(r)?;
@@ -3782,10 +3809,22 @@ impl Readable for UnsignedNodeAnnouncement {
37823809
}
37833810
}
37843811

3785-
impl_writeable!(NodeAnnouncement, {
3786-
signature,
3787-
contents
3788-
});
3812+
impl Writeable for NodeAnnouncement {
3813+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
3814+
self.signature.write(w)?;
3815+
self.contents.write(w)?;
3816+
Ok(())
3817+
}
3818+
}
3819+
3820+
impl LengthReadable for NodeAnnouncement {
3821+
fn read_from_fixed_length_buffer<R: LengthLimitedRead>(r: &mut R) -> Result<Self, DecodeError> {
3822+
Ok(Self {
3823+
signature: Readable::read(r)?,
3824+
contents: LengthReadable::read_from_fixed_length_buffer(r)?,
3825+
})
3826+
}
3827+
}
37893828

37903829
impl Readable for QueryShortChannelIds {
37913830
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {

lightning/src/ln/wire.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -358,10 +358,14 @@ where
358358
LengthReadable::read_from_fixed_length_buffer(buffer)?,
359359
)),
360360
msgs::ChannelAnnouncement::TYPE => {
361-
Ok(Message::ChannelAnnouncement(Readable::read(buffer)?))
361+
Ok(Message::ChannelAnnouncement(LengthReadable::read_from_fixed_length_buffer(buffer)?))
362+
},
363+
msgs::NodeAnnouncement::TYPE => {
364+
Ok(Message::NodeAnnouncement(LengthReadable::read_from_fixed_length_buffer(buffer)?))
365+
},
366+
msgs::ChannelUpdate::TYPE => {
367+
Ok(Message::ChannelUpdate(LengthReadable::read_from_fixed_length_buffer(buffer)?))
362368
},
363-
msgs::NodeAnnouncement::TYPE => Ok(Message::NodeAnnouncement(Readable::read(buffer)?)),
364-
msgs::ChannelUpdate::TYPE => Ok(Message::ChannelUpdate(Readable::read(buffer)?)),
365369
msgs::QueryShortChannelIds::TYPE => {
366370
Ok(Message::QueryShortChannelIds(Readable::read(buffer)?))
367371
},

lightning/src/routing/gossip.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -2730,7 +2730,7 @@ pub(crate) mod tests {
27302730
use crate::types::features::InitFeatures;
27312731
use crate::util::config::UserConfig;
27322732
use crate::util::scid_utils::scid_from_parts;
2733-
use crate::util::ser::{Hostname, Readable, ReadableArgs, Writeable};
2733+
use crate::util::ser::{Hostname, LengthReadable, Readable, ReadableArgs, Writeable};
27342734
use crate::util::test_utils;
27352735

27362736
use super::STALE_CHANNEL_UPDATE_AGE_LIMIT_SECS;
@@ -4301,7 +4301,8 @@ pub(crate) mod tests {
43014301
// 1. Check we can read a valid NodeAnnouncementInfo and fail on an invalid one
43024302
let announcement_message = <Vec<u8>>::from_hex("d977cb9b53d93a6ff64bb5f1e158b4094b66e798fb12911168a3ccdf80a83096340a6a95da0ae8d9f776528eecdbb747eb6b545495a4319ed5378e35b21e073a000122013413a7031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f2020201010101010101010101010101010101010101010101010101010101010101010000701fffefdfc2607").unwrap();
43034303
let announcement_message =
4304-
NodeAnnouncement::read(&mut announcement_message.as_slice()).unwrap();
4304+
NodeAnnouncement::read_from_fixed_length_buffer(&mut announcement_message.as_slice())
4305+
.unwrap();
43054306
let valid_node_ann_info = NodeAnnouncementInfo::Relayed(announcement_message);
43064307

43074308
let mut encoded_valid_node_ann_info = Vec::new();

lightning/src/util/ser.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1330,14 +1330,14 @@ impl<T: Writeable> Writeable for Option<T> {
13301330
}
13311331
}
13321332

1333-
impl<T: Readable> Readable for Option<T> {
1333+
impl<T: LengthReadable> Readable for Option<T> {
13341334
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
13351335
let len: BigSize = Readable::read(r)?;
13361336
match len.0 {
13371337
0 => Ok(None),
13381338
len => {
13391339
let mut reader = FixedLengthReader::new(r, len - 1);
1340-
Ok(Some(Readable::read(&mut reader)?))
1340+
Ok(Some(LengthReadable::read_from_fixed_length_buffer(&mut reader)?))
13411341
},
13421342
}
13431343
}

0 commit comments

Comments
 (0)