diff --git a/Cargo.toml b/Cargo.toml index ab63e3c..29269ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,7 @@ bitflags = {version="2.3.3", features = ["serde"], optional = true} ####################### # Parser dependencies # ####################### -bytes = {version = "1.4.0", optional = true} +bytes = {version = "1.5.0", optional = true} hex= {version = "0.4.3", optional = true} # bmp/openbmp parsing log= {version = "0.4", optional = true } oneio = {version= "0.16.0", default-features = false, features = ["lib-core"], optional = true } diff --git a/src/error.rs b/src/error.rs index 6e6eacb..ca3d13d 100644 --- a/src/error.rs +++ b/src/error.rs @@ -11,7 +11,6 @@ use std::{error::Error, fmt, io}; #[derive(Debug)] pub enum ParserError { IoError(io::Error), - IoNotEnoughBytes(), EofError(io::Error), OneIoError(OneIoError), EofExpected, @@ -50,7 +49,6 @@ impl Display for ParserError { ParserError::EofExpected => write!(f, "Error: reach end of file"), ParserError::OneIoError(e) => write!(f, "Error: {}", e), ParserError::FilterError(e) => write!(f, "Error: {}", e), - ParserError::IoNotEnoughBytes() => write!(f, "Error: Not enough bytes to read"), } } } diff --git a/src/parser/bgp/attributes/mod.rs b/src/parser/bgp/attributes/mod.rs index 9c32fba..dac4d58 100644 --- a/src/parser/bgp/attributes/mod.rs +++ b/src/parser/bgp/attributes/mod.rs @@ -127,6 +127,7 @@ pub fn parse_attributes( } // we know data has enough bytes to read, so we can split the bytes into a new Bytes object + data.has_n_remaining(attr_length)?; let mut attr_data = data.split_to(attr_length); let attr = match attr_type { diff --git a/src/parser/bgp/messages.rs b/src/parser/bgp/messages.rs index 00eb792..a1b7b5a 100644 --- a/src/parser/bgp/messages.rs +++ b/src/parser/bgp/messages.rs @@ -76,6 +76,7 @@ pub fn parse_bgp_message( data.remaining() ); } + data.has_n_remaining(bgp_msg_length)?; let mut msg_data = data.split_to(bgp_msg_length); Ok(match msg_type { @@ -279,11 +280,12 @@ pub fn parse_bgp_update_message( add_path: bool, asn_len: &AsnLength, ) -> Result { - // NOTE: AFI for routes out side attributes are IPv4 ONLY. + // NOTE: AFI for routes outside attributes are IPv4 ONLY. let afi = Afi::Ipv4; - // parse withdrawn prefixes nlri + // parse withdrawn prefixes NLRI let withdrawn_bytes_length = input.read_u16()? as usize; + input.has_n_remaining(withdrawn_bytes_length)?; let withdrawn_bytes = input.split_to(withdrawn_bytes_length); let withdrawn_prefixes = read_nlri(withdrawn_bytes, &afi, add_path)?; diff --git a/src/parser/bmp/messages/route_mirroring.rs b/src/parser/bmp/messages/route_mirroring.rs index 753150f..98c6613 100644 --- a/src/parser/bmp/messages/route_mirroring.rs +++ b/src/parser/bmp/messages/route_mirroring.rs @@ -39,6 +39,7 @@ pub fn parse_route_mirroring( match data.read_u16()? { 0 => { let info_len = data.read_u16()?; + data.has_n_remaining(info_len as usize)?; let mut bytes = data.split_to(info_len as usize); let value = parse_bgp_message(&mut bytes, false, asn_len)?; tlvs.push(RouteMirroringTlv { diff --git a/src/parser/bmp/mod.rs b/src/parser/bmp/mod.rs index 6f7c3a2..ffb8b31 100644 --- a/src/parser/bmp/mod.rs +++ b/src/parser/bmp/mod.rs @@ -4,6 +4,7 @@ Provides parsing for BMP and OpenBMP binary-formatted messages. use crate::parser::bmp::error::ParserBmpError; use crate::parser::bmp::messages::*; pub use crate::parser::bmp::openbmp::parse_openbmp_header; +use crate::utils::ReadUtils; use bytes::Bytes; pub mod error; @@ -24,7 +25,9 @@ pub fn parse_openbmp_msg(mut data: Bytes) -> Result pub fn parse_bmp_msg(data: &mut Bytes) -> Result { let common_header = parse_bmp_common_header(data)?; - let mut content = data.split_to(common_header.msg_len as usize - 6); + let content_length = common_header.msg_len as usize - 6; + data.has_n_remaining(content_length)?; + let mut content = data.split_to(content_length); // if total_len>common_header.msg_len { // // truncated message diff --git a/src/parser/iters.rs b/src/parser/iters.rs index dd6f193..a1bd1c2 100644 --- a/src/parser/iters.rs +++ b/src/parser/iters.rs @@ -114,9 +114,7 @@ impl Iterator for RecordIterator { } None } - ParserError::OneIoError(_) - | ParserError::FilterError(_) - | ParserError::IoNotEnoughBytes() => { + ParserError::OneIoError(_) | ParserError::FilterError(_) => { // this should not happen at this stage None } diff --git a/src/parser/mrt/messages/table_dump_v2/rib_afi_entries.rs b/src/parser/mrt/messages/table_dump_v2/rib_afi_entries.rs index fcd1c0b..b0110cb 100644 --- a/src/parser/mrt/messages/table_dump_v2/rib_afi_entries.rs +++ b/src/parser/mrt/messages/table_dump_v2/rib_afi_entries.rs @@ -125,10 +125,7 @@ pub fn parse_rib_entry( } let attribute_length = input.read_u16()? as usize; - if input.remaining() < attribute_length { - return Err(ParserError::TruncatedMsg("truncated msg".to_string())); - } - + input.has_n_remaining(attribute_length)?; let attr_data_slice = input.split_to(attribute_length); let attributes = parse_attributes( attr_data_slice, diff --git a/src/parser/utils.rs b/src/parser/utils.rs index 5076d70..0826194 100644 --- a/src/parser/utils.rs +++ b/src/parser/utils.rs @@ -14,7 +14,7 @@ use log::debug; use std::net::IpAddr; use crate::error::ParserError; -use crate::ParserError::IoNotEnoughBytes; +use crate::ParserError::TruncatedMsg; impl ReadUtils for Bytes {} @@ -22,8 +22,12 @@ impl ReadUtils for Bytes {} pub trait ReadUtils: Buf { #[inline] fn has_n_remaining(&self, n: usize) -> Result<(), ParserError> { - if self.remaining() < n { - Err(IoNotEnoughBytes()) + let remaining = self.remaining(); + if remaining < n { + Err(TruncatedMsg(format!( + "not enough bytes to read. remaining: {}, required: {}", + remaining, n + ))) } else { Ok(()) }