Limit TLV stream decoding to type ranges
[rust-lightning] / lightning / src / offers / parse.rs
index 032e95b3cc52199a095c29a78c064abed2b6c40f..19d7d74ed6111fd6ddc9fef9d7410a8a47b43354 100644 (file)
@@ -13,7 +13,9 @@ use bitcoin::bech32;
 use bitcoin::bech32::{FromBase32, ToBase32};
 use core::convert::TryFrom;
 use core::fmt;
+use crate::io;
 use crate::ln::msgs::DecodeError;
+use crate::util::ser::SeekReadable;
 
 use crate::prelude::*;
 
@@ -74,6 +76,30 @@ impl<'a> AsRef<str> for Bech32String<'a> {
        }
 }
 
+/// A wrapper for reading a message as a TLV stream `T` from a byte sequence, while still
+/// maintaining ownership of the bytes for later use.
+pub(crate) struct ParsedMessage<T: SeekReadable> {
+       pub bytes: Vec<u8>,
+       pub tlv_stream: T,
+}
+
+impl<T: SeekReadable> TryFrom<Vec<u8>> for ParsedMessage<T> {
+       type Error = DecodeError;
+
+       fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
+               let mut cursor = io::Cursor::new(bytes);
+               let tlv_stream: T = SeekReadable::read(&mut cursor)?;
+
+               // Ensure that there are no more TLV records left to parse.
+               if cursor.position() < cursor.get_ref().len() as u64 {
+                       return Err(DecodeError::InvalidValue);
+               }
+
+               let bytes = cursor.into_inner();
+               Ok(Self { bytes, tlv_stream })
+       }
+}
+
 /// Error when parsing a bech32 encoded message using [`str::parse`].
 #[derive(Debug, PartialEq)]
 pub enum ParseError {