Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Require LengthLimitedRead for structs that always drain reader #3640

Merged
4 changes: 2 additions & 2 deletions fuzz/src/chanmon_consistency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ use lightning::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret};
use lightning::util::config::UserConfig;
use lightning::util::hash_tables::*;
use lightning::util::logger::Logger;
use lightning::util::ser::{Readable, ReadableArgs, Writeable, Writer};
use lightning::util::ser::{LengthReadable, ReadableArgs, Writeable, Writer};
use lightning::util::test_channel_signer::{EnforcementState, TestChannelSigner};

use lightning_invoice::RawBolt11Invoice;
Expand Down Expand Up @@ -1103,7 +1103,7 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
// update_fail_htlc as we do when we reject a payment.
let mut msg_ser = update_add.encode();
msg_ser[1000] ^= 0xff;
let new_msg = UpdateAddHTLC::read(&mut Cursor::new(&msg_ser)).unwrap();
let new_msg = UpdateAddHTLC::read_from_fixed_length_buffer(&mut &msg_ser[..]).unwrap();
dest.handle_update_add_htlc(nodes[$node].get_our_node_id(), &new_msg);
}
}
Expand Down
39 changes: 21 additions & 18 deletions fuzz/src/msg_targets/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,16 @@ impl Writer for VecWriter {
#[macro_export]
macro_rules! test_msg {
($MsgType: path, $data: ident) => {{
use lightning::util::ser::{Readable, Writeable};
let mut r = ::lightning::io::Cursor::new($data);
if let Ok(msg) = <$MsgType as Readable>::read(&mut r) {
let p = r.position() as usize;
use lightning::util::ser::{LengthReadable, Writeable};
let mut r = &$data[..];
if let Ok(msg) = <$MsgType as LengthReadable>::read_from_fixed_length_buffer(&mut r) {
let p = $data.len() - r.len() as usize;
let mut w = VecWriter(Vec::new());
msg.write(&mut w).unwrap();

assert_eq!(w.0.len(), p);
assert_eq!(msg.serialized_length(), p);
assert_eq!(&r.into_inner()[..p], &w.0[..p]);
assert_eq!(&$data[..p], &w.0[..p]);
}
}};
}
Expand All @@ -49,15 +49,16 @@ macro_rules! test_msg {
#[macro_export]
macro_rules! test_msg_simple {
($MsgType: path, $data: ident) => {{
use lightning::util::ser::{Readable, Writeable};
let mut r = ::lightning::io::Cursor::new($data);
if let Ok(msg) = <$MsgType as Readable>::read(&mut r) {
use lightning::util::ser::{LengthReadable, Writeable};
if let Ok(msg) =
<$MsgType as LengthReadable>::read_from_fixed_length_buffer(&mut &$data[..])
{
let mut w = VecWriter(Vec::new());
msg.write(&mut w).unwrap();
assert_eq!(msg.serialized_length(), w.0.len());

let msg =
<$MsgType as Readable>::read(&mut ::lightning::io::Cursor::new(&w.0)).unwrap();
<$MsgType as LengthReadable>::read_from_fixed_length_buffer(&mut &w.0[..]).unwrap();
let mut w_two = VecWriter(Vec::new());
msg.write(&mut w_two).unwrap();
assert_eq!(&w.0[..], &w_two.0[..]);
Expand All @@ -70,12 +71,13 @@ macro_rules! test_msg_simple {
#[macro_export]
macro_rules! test_msg_exact {
($MsgType: path, $data: ident) => {{
use lightning::util::ser::{Readable, Writeable};
let mut r = ::lightning::io::Cursor::new($data);
if let Ok(msg) = <$MsgType as Readable>::read(&mut r) {
use lightning::util::ser::{LengthReadable, Writeable};
if let Ok(msg) =
<$MsgType as LengthReadable>::read_from_fixed_length_buffer(&mut &$data[..])
{
let mut w = VecWriter(Vec::new());
msg.write(&mut w).unwrap();
assert_eq!(&r.into_inner()[..], &w.0[..]);
assert_eq!(&$data[..], &w.0[..]);
assert_eq!(msg.serialized_length(), w.0.len());
}
}};
Expand All @@ -86,17 +88,18 @@ macro_rules! test_msg_exact {
#[macro_export]
macro_rules! test_msg_hole {
($MsgType: path, $data: ident, $hole: expr, $hole_len: expr) => {{
use lightning::util::ser::{Readable, Writeable};
let mut r = ::lightning::io::Cursor::new($data);
if let Ok(msg) = <$MsgType as Readable>::read(&mut r) {
use lightning::util::ser::{LengthReadable, Writeable};
if let Ok(msg) =
<$MsgType as LengthReadable>::read_from_fixed_length_buffer(&mut &$data[..])
{
let mut w = VecWriter(Vec::new());
msg.write(&mut w).unwrap();
let p = w.0.len() as usize;
assert_eq!(msg.serialized_length(), p);

assert_eq!(w.0.len(), p);
assert_eq!(&r.get_ref()[..$hole], &w.0[..$hole]);
assert_eq!(&r.get_ref()[$hole + $hole_len..p], &w.0[$hole + $hole_len..]);
assert_eq!(&$data[..$hole], &w.0[..$hole]);
assert_eq!(&$data[$hole + $hole_len..p], &w.0[$hole + $hole_len..]);
}
}};
}
9 changes: 6 additions & 3 deletions fuzz/src/onion_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,23 @@ use lightning::onion_message::packet::OnionMessageContents;
use lightning::sign::{EntropySource, NodeSigner, Recipient, SignerProvider};
use lightning::types::features::InitFeatures;
use lightning::util::logger::Logger;
use lightning::util::ser::{Readable, Writeable, Writer};
use lightning::util::ser::{LengthReadable, Writeable, Writer};
use lightning::util::test_channel_signer::TestChannelSigner;

use lightning_invoice::RawBolt11Invoice;

use crate::utils::test_logger;

use lightning::io::{self, Cursor};
use lightning::io;
use std::sync::atomic::{AtomicU64, Ordering};

#[inline]
/// Actual fuzz test, method signature and name are fixed
pub fn do_test<L: Logger>(data: &[u8], logger: &L) {
if let Ok(msg) = <msgs::OnionMessage as Readable>::read(&mut Cursor::new(data)) {
let mut reader = &data[..];
if let Ok(msg) =
<msgs::OnionMessage as LengthReadable>::read_from_fixed_length_buffer(&mut reader)
{
let mut secret_bytes = [1; 32];
secret_bytes[31] = 2;
let secret = SecretKey::from_slice(&secret_bytes).unwrap();
Expand Down
9 changes: 5 additions & 4 deletions fuzz/src/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use lightning::routing::utxo::{UtxoFuture, UtxoLookup, UtxoLookupError, UtxoResu
use lightning::types::features::{BlindedHopFeatures, Bolt12InvoiceFeatures};
use lightning::util::config::UserConfig;
use lightning::util::hash_tables::*;
use lightning::util::ser::Readable;
use lightning::util::ser::LengthReadable;

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

macro_rules! decode_msg {
($MsgType: path, $len: expr) => {{
let mut reader = ::lightning::io::Cursor::new(get_slice!($len));
match <$MsgType>::read(&mut reader) {
let data = get_slice!($len);
let mut reader = &data[..];
match <$MsgType>::read_from_fixed_length_buffer(&mut reader) {
Ok(msg) => {
assert_eq!(reader.position(), $len as u64);
assert_eq!(reader.len(), $len);
msg
},
Err(e) => match e {
Expand Down
10 changes: 5 additions & 5 deletions lightning-custom-message/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
//! use lightning::ln::peer_handler::CustomMessageHandler;
//! use lightning::ln::wire::{CustomMessageReader, self};
//! # use lightning::types::features::{InitFeatures, NodeFeatures};
//! use lightning::util::ser::Writeable;
//! use lightning::util::ser::{LengthLimitedRead, Writeable};
//! # use lightning::util::ser::Writer;
//!
//! // Assume that `FooHandler` and `BarHandler` are defined in one crate and `BazHandler` is
Expand Down Expand Up @@ -52,7 +52,7 @@
//! impl CustomMessageReader for FooHandler {
//! // ...
//! # type CustomMessage = Foo;
//! # fn read<R: io::Read>(
//! # fn read<R: LengthLimitedRead>(
//! # &self, _message_type: u16, _buffer: &mut R
//! # ) -> Result<Option<Self::CustomMessage>, DecodeError> {
//! # unimplemented!()
Expand Down Expand Up @@ -104,7 +104,7 @@
//! impl CustomMessageReader for BarHandler {
//! // ...
//! # type CustomMessage = Bar;
//! # fn read<R: io::Read>(
//! # fn read<R: LengthLimitedRead>(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to rename CustomMessageReader::read to match the LengthReadable version?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the reason we renamed the method last time was to avoid conflicting implementations between LengthReadable::read and Readable::read, which doesn't seem to be the case here? But I'm happy to rename it if you prefer.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its also clearer to the reader, but we can leave it too. It should remain clear given the buffer type is restricted.

//! # &self, _message_type: u16, _buffer: &mut R
//! # ) -> Result<Option<Self::CustomMessage>, DecodeError> {
//! # unimplemented!()
Expand Down Expand Up @@ -156,7 +156,7 @@
//! impl CustomMessageReader for BazHandler {
//! // ...
//! # type CustomMessage = Baz;
//! # fn read<R: io::Read>(
//! # fn read<R: LengthLimitedRead>(
//! # &self, _message_type: u16, _buffer: &mut R
//! # ) -> Result<Option<Self::CustomMessage>, DecodeError> {
//! # unimplemented!()
Expand Down Expand Up @@ -340,7 +340,7 @@ macro_rules! composite_custom_message_handler {

impl $crate::lightning::ln::wire::CustomMessageReader for $handler {
type CustomMessage = $message;
fn read<R: $crate::lightning::io::Read>(
fn read<R: $crate::lightning::util::ser::LengthLimitedRead>(
&self, message_type: u16, buffer: &mut R
) -> Result<Option<Self::CustomMessage>, $crate::lightning::ln::msgs::DecodeError> {
match message_type {
Expand Down
11 changes: 6 additions & 5 deletions lightning-liquidity/src/lsps0/ser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ use crate::lsps2::msgs::{
};
use crate::prelude::{HashMap, String};

use lightning::ln::msgs::LightningError;
use lightning::ln::msgs::{DecodeError, LightningError};
use lightning::ln::wire;
use lightning::util::ser::WithoutLength;
use lightning::util::ser::{LengthLimitedRead, LengthReadable, WithoutLength};

use bitcoin::secp256k1::PublicKey;

Expand Down Expand Up @@ -168,9 +168,10 @@ impl lightning::util::ser::Writeable for RawLSPSMessage {
}
}

impl lightning::util::ser::Readable for RawLSPSMessage {
fn read<R: lightning::io::Read>(r: &mut R) -> Result<Self, lightning::ln::msgs::DecodeError> {
let payload_without_length = WithoutLength::read(r)?;
impl LengthReadable for RawLSPSMessage {
fn read_from_fixed_length_buffer<R: LengthLimitedRead>(r: &mut R) -> Result<Self, DecodeError> {
let payload_without_length: WithoutLength<String> =
LengthReadable::read_from_fixed_length_buffer(r)?;
Ok(Self { payload: payload_without_length.0 })
}
}
Expand Down
8 changes: 5 additions & 3 deletions lightning-liquidity/src/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use lightning::ln::peer_handler::CustomMessageHandler;
use lightning::ln::wire::CustomMessageReader;
use lightning::sign::EntropySource;
use lightning::util::logger::Level;
use lightning::util::ser::Readable;
use lightning::util::ser::{LengthLimitedRead, LengthReadable};

use lightning_types::features::{InitFeatures, NodeFeatures};

Expand Down Expand Up @@ -449,11 +449,13 @@ where
{
type CustomMessage = RawLSPSMessage;

fn read<RD: lightning::io::Read>(
fn read<RD: LengthLimitedRead>(
&self, message_type: u16, buffer: &mut RD,
) -> Result<Option<Self::CustomMessage>, lightning::ln::msgs::DecodeError> {
match message_type {
LSPS_MESSAGE_TYPE_ID => Ok(Some(RawLSPSMessage::read(buffer)?)),
LSPS_MESSAGE_TYPE_ID => {
Ok(Some(RawLSPSMessage::read_from_fixed_length_buffer(buffer)?))
},
_ => Ok(None),
}
}
Expand Down
14 changes: 7 additions & 7 deletions lightning/src/crypto/streams.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::crypto::chacha20poly1305rfc::ChaCha20Poly1305RFC;
use crate::io::{self, Read, Write};
use crate::ln::msgs::DecodeError;
use crate::util::ser::{
FixedLengthReader, LengthRead, LengthReadableArgs, Readable, Writeable, Writer,
FixedLengthReader, LengthLimitedRead, LengthReadableArgs, Readable, Writeable, Writer,
};

pub(crate) struct ChaChaReader<'a, R: io::Read> {
Expand Down Expand Up @@ -56,16 +56,16 @@ pub(crate) struct ChaChaPolyReadAdapter<R: Readable> {
}

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

let mut chacha = ChaCha20Poly1305RFC::new(&secret, &[0; 12], &[]);
let decrypted_len = r.total_bytes() - 16;
let decrypted_len = r.remaining_bytes() - 16;
let s = FixedLengthReader::new(r, decrypted_len);
let mut chacha_stream = ChaChaPolyReader { chacha: &mut chacha, read: s };
let readable: T = Readable::read(&mut chacha_stream)?;
Expand Down
6 changes: 3 additions & 3 deletions lightning/src/ln/channelmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ use crate::util::config::{ChannelConfig, ChannelConfigUpdate, ChannelConfigOverr
use crate::util::wakers::{Future, Notifier};
use crate::util::scid_utils::fake_scid;
use crate::util::string::UntrustedString;
use crate::util::ser::{BigSize, FixedLengthReader, Readable, ReadableArgs, MaybeReadable, Writeable, Writer, VecWriter};
use crate::util::ser::{BigSize, FixedLengthReader, LengthReadable, Readable, ReadableArgs, MaybeReadable, Writeable, Writer, VecWriter};
use crate::util::logger::{Level, Logger, WithContext};
use crate::util::errors::APIError;
#[cfg(async_payments)] use {
Expand Down Expand Up @@ -12843,14 +12843,14 @@ impl Readable for HTLCFailureMsg {
2 => {
let length: BigSize = Readable::read(reader)?;
let mut s = FixedLengthReader::new(reader, length.0);
let res = Readable::read(&mut s)?;
let res = LengthReadable::read_from_fixed_length_buffer(&mut s)?;
s.eat_remaining()?; // Return ShortRead if there's actually not enough bytes
Ok(HTLCFailureMsg::Relay(res))
},
3 => {
let length: BigSize = Readable::read(reader)?;
let mut s = FixedLengthReader::new(reader, length.0);
let res = Readable::read(&mut s)?;
let res = LengthReadable::read_from_fixed_length_buffer(&mut s)?;
s.eat_remaining()?; // Return ShortRead if there's actually not enough bytes
Ok(HTLCFailureMsg::Malformed(res))
},
Expand Down
Loading
Loading