Skip to content

Commit 96a21ce

Browse files
Rename LengthRead to LengthLimitedRead
In general, the codebase currently tends to use the Readable trait with two different semantics -- some objects know when to stop reading because they have a length prefix and some automatically read to the end of the reader. This differing usage can lead to bugs. For objects that read-to-end, it would be much safer if the compiler enforced that they could only be read from a length-limiting reader. We already have a LengthRead trait that requires the underlying reader to provide the length, which is similar to what we want. So rather than adding an additional trait, here we rename LengthRead and update its semantics to require a fixed length reader. Upcoming commits will switch read-to-end structs that are currently read with Readable to use LengthReadable with LengthLimitedRead instead.
1 parent e6267d3 commit 96a21ce

File tree

4 files changed

+28
-20
lines changed

4 files changed

+28
-20
lines changed

lightning/src/crypto/streams.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::crypto::chacha20poly1305rfc::ChaCha20Poly1305RFC;
44
use crate::io::{self, Read, Write};
55
use crate::ln::msgs::DecodeError;
66
use crate::util::ser::{
7-
FixedLengthReader, LengthRead, LengthReadableArgs, Readable, Writeable, Writer,
7+
FixedLengthReader, LengthLimitedRead, LengthReadableArgs, Readable, Writeable, Writer,
88
};
99

1010
pub(crate) struct ChaChaReader<'a, R: io::Read> {
@@ -56,10 +56,10 @@ pub(crate) struct ChaChaPolyReadAdapter<R: Readable> {
5656
}
5757

5858
impl<T: Readable> LengthReadableArgs<[u8; 32]> for ChaChaPolyReadAdapter<T> {
59-
// Simultaneously read and decrypt an object from a LengthRead, storing it in Self::readable.
60-
// LengthRead must be used instead of std::io::Read because we need the total length to separate
61-
// out the tag at the end.
62-
fn read<R: LengthRead>(r: &mut R, secret: [u8; 32]) -> Result<Self, DecodeError> {
59+
// Simultaneously read and decrypt an object from a LengthLimitedRead storing it in
60+
// Self::readable. LengthLimitedRead must be used instead of std::io::Read because we need the
61+
// total length to separate out the tag at the end.
62+
fn read<R: LengthLimitedRead>(r: &mut R, secret: [u8; 32]) -> Result<Self, DecodeError> {
6363
if r.total_bytes() < 16 {
6464
return Err(DecodeError::InvalidValue);
6565
}

lightning/src/ln/msgs.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ use crate::io_extras::read_to_end;
5959

6060
use crate::crypto::streams::ChaChaPolyReadAdapter;
6161
use crate::util::logger;
62-
use crate::util::ser::{BigSize, FixedLengthReader, HighZeroBytesDroppedBigSize, Hostname, LengthRead, LengthReadable, LengthReadableArgs, Readable, ReadableArgs, TransactionU16LenLimited, WithoutLength, Writeable, Writer};
62+
use crate::util::ser::{BigSize, FixedLengthReader, HighZeroBytesDroppedBigSize, Hostname, LengthLimitedRead, LengthReadable, LengthReadableArgs, Readable, ReadableArgs, TransactionU16LenLimited, WithoutLength, Writeable, Writer};
6363
use crate::util::base32;
6464

6565
use crate::routing::gossip::{NodeAlias, NodeId};
@@ -2323,7 +2323,7 @@ impl Writeable for TrampolineOnionPacket {
23232323
}
23242324

23252325
impl LengthReadable for TrampolineOnionPacket {
2326-
fn read_from_fixed_length_buffer<R: LengthRead>(r: &mut R) -> Result<Self, DecodeError> {
2326+
fn read_from_fixed_length_buffer<R: LengthLimitedRead>(r: &mut R) -> Result<Self, DecodeError> {
23272327
let version = Readable::read(r)?;
23282328
let public_key = Readable::read(r)?;
23292329

lightning/src/onion_message/packet.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use crate::ln::msgs::DecodeError;
2323
use crate::ln::onion_utils;
2424
use crate::util::logger::Logger;
2525
use crate::util::ser::{
26-
BigSize, FixedLengthReader, LengthRead, LengthReadable, LengthReadableArgs, Readable,
26+
BigSize, FixedLengthReader, LengthLimitedRead, LengthReadable, LengthReadableArgs, Readable,
2727
ReadableArgs, Writeable, Writer,
2828
};
2929

@@ -83,7 +83,7 @@ impl Writeable for Packet {
8383
}
8484

8585
impl LengthReadable for Packet {
86-
fn read_from_fixed_length_buffer<R: LengthRead>(r: &mut R) -> Result<Self, DecodeError> {
86+
fn read_from_fixed_length_buffer<R: LengthLimitedRead>(r: &mut R) -> Result<Self, DecodeError> {
8787
const READ_BUFFER_SIZE: usize = 4096;
8888

8989
let version = Readable::read(r)?;

lightning/src/util/ser.rs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ impl<'a, R: Read> Read for FixedLengthReader<'a, R> {
226226
}
227227
}
228228

229-
impl<'a, R: Read> LengthRead for FixedLengthReader<'a, R> {
229+
impl<'a, R: Read> LengthLimitedRead for FixedLengthReader<'a, R> {
230230
#[inline]
231231
fn total_bytes(&self) -> u64 {
232232
self.total_bytes
@@ -344,8 +344,10 @@ where
344344
fn read<R: Read>(reader: &mut R, params: P) -> Result<Self, DecodeError>;
345345
}
346346

347-
/// A [`io::Read`] that also provides the total bytes available to be read.
348-
pub trait LengthRead: Read {
347+
/// A [`io::Read`] that limits the amount of bytes that can be read. Implementations should ensure
348+
/// that the object being read will only consume a fixed number of bytes from the underlying
349+
/// [`io::Read`], see [`FixedLengthReader`] for an example.
350+
pub trait LengthLimitedRead: Read {
349351
/// The total number of bytes available to be read.
350352
fn total_bytes(&self) -> u64;
351353
}
@@ -357,26 +359,30 @@ pub(crate) trait LengthReadableArgs<P>
357359
where
358360
Self: Sized,
359361
{
360-
/// Reads a `Self` in from the given [`LengthRead`].
361-
fn read<R: LengthRead>(reader: &mut R, params: P) -> Result<Self, DecodeError>;
362+
/// Reads a `Self` in from the given [`LengthLimitedRead`].
363+
fn read<R: LengthLimitedRead>(reader: &mut R, params: P) -> Result<Self, DecodeError>;
362364
}
363365

364-
/// A trait that allows the implementer to be read in from a [`LengthRead`], requiring
365-
/// the reader to provide the total length of the read.
366+
/// A trait that allows the implementer to be read in from a [`LengthLimitedRead`], requiring the
367+
/// reader to provide the total length of the read.
366368
///
367369
/// Any type that implements [`Readable`] also automatically has a [`LengthReadable`]
368370
/// implementation, but some types, most notably onion packets, only implement [`LengthReadable`].
369371
pub trait LengthReadable
370372
where
371373
Self: Sized,
372374
{
373-
/// Reads a `Self` in from the given [`LengthRead`].
374-
fn read_from_fixed_length_buffer<R: LengthRead>(reader: &mut R) -> Result<Self, DecodeError>;
375+
/// Reads a `Self` in from the given [`LengthLimitedRead`].
376+
fn read_from_fixed_length_buffer<R: LengthLimitedRead>(
377+
reader: &mut R,
378+
) -> Result<Self, DecodeError>;
375379
}
376380

377381
impl<T: Readable> LengthReadable for T {
378382
#[inline]
379-
fn read_from_fixed_length_buffer<R: LengthRead>(reader: &mut R) -> Result<T, DecodeError> {
383+
fn read_from_fixed_length_buffer<R: LengthLimitedRead>(
384+
reader: &mut R,
385+
) -> Result<T, DecodeError> {
380386
Readable::read(reader)
381387
}
382388
}
@@ -405,7 +411,9 @@ impl<T: Readable> MaybeReadable for T {
405411
pub struct RequiredWrapper<T>(pub Option<T>);
406412
impl<T: LengthReadable> LengthReadable for RequiredWrapper<T> {
407413
#[inline]
408-
fn read_from_fixed_length_buffer<R: LengthRead>(reader: &mut R) -> Result<Self, DecodeError> {
414+
fn read_from_fixed_length_buffer<R: LengthLimitedRead>(
415+
reader: &mut R,
416+
) -> Result<Self, DecodeError> {
409417
Ok(Self(Some(LengthReadable::read_from_fixed_length_buffer(reader)?)))
410418
}
411419
}

0 commit comments

Comments
 (0)