1 use crate::{err::Layer, LenSource}; 2 3 /// Error when different lengths are conflicting with each other (e.g. not 4 /// enough data in a slice to decode a header). 5 /// 6 /// This error is triggered whenever there is not enough data to decode 7 /// an element (e.g. if a slice is too small to decode an header) or 8 /// if a length that is inhered from an upper layer is too big for the 9 /// lower layer (e.g. length inherited from an IP header is too big to 10 /// be used as an ICMP packet length). 11 /// 12 /// When the error is caused by not enough data being available 13 /// `required_len > len` must be true. While when the length from 14 /// the upper layer is too big for the lower layer the inverse 15 /// (`required_len < len`) must be true. 16 /// 17 /// # Examples: 18 /// 19 /// An example for an error that could be returned when there is not enough 20 /// data available to decode an UDP header would be: 21 /// 22 /// ``` 23 /// use etherparse::*; 24 /// 25 /// err::LenError{ 26 /// // Expected to have at least the length of an UDP header present: 27 /// required_len: UdpHeader::LEN, 28 /// // Could not decode the UDP header: 29 /// layer: err::Layer::UdpHeader, 30 /// // There was only 1 byte left (not enough for an UDP header): 31 /// len: 1, 32 /// // The provided length was determined by the total length field in the 33 /// // IPv4 header: 34 /// len_source: LenSource::Ipv4HeaderTotalLen, 35 /// // Offset in bytes from the start of decoding (ethernet in this) case 36 /// // to the expected UDP header start: 37 /// layer_start_offset: Ethernet2Header::LEN + Ipv4Header::MIN_LEN 38 /// }; 39 /// ``` 40 #[derive(Clone, Debug, Eq, PartialEq, Hash)] 41 pub struct LenError { 42 /// Expected minimum or maximum length conflicting with the 43 /// `len` value. 44 pub required_len: usize, 45 46 /// Length limiting or exceeding the required length. 47 pub len: usize, 48 49 /// Source of the outer length (e.g. Slice or a length specified by 50 /// an upper level protocol). 51 pub len_source: LenSource, 52 53 /// Layer in which the length error was encountered. 54 pub layer: Layer, 55 56 /// Offset from the start of the parsed data to the layer where the 57 /// length error occurred. 58 pub layer_start_offset: usize, 59 } 60 61 impl LenError { 62 /// Adds an offset value to the `layer_start_offset` field. 63 #[inline] add_offset(self, offset: usize) -> Self64 pub const fn add_offset(self, offset: usize) -> Self { 65 LenError { 66 required_len: self.required_len, 67 layer: self.layer, 68 len: self.len, 69 len_source: self.len_source, 70 layer_start_offset: self.layer_start_offset + offset, 71 } 72 } 73 } 74 75 impl core::fmt::Display for LenError { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result76 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 77 let len_source: &'static str = { 78 use LenSource::*; 79 match self.len_source { 80 Slice => "slice length", 81 Ipv4HeaderTotalLen => "length calculated from the IPv4 header 'total length' field", 82 Ipv6HeaderPayloadLen => { 83 "length calculated from the IPv6 header 'payload length' field" 84 } 85 UdpHeaderLen => "length calculated from the UDP header 'length' field", 86 TcpHeaderLen => "length calculated from the TCP header 'length' field", 87 ArpAddrLengths => { 88 "length calculated from the ARP 'hw_addr_size' & 'proto_addr_size' fields" 89 } 90 } 91 }; 92 93 if self.required_len > self.len { 94 if self.layer_start_offset > 0 { 95 write!( 96 f, 97 "{}: Not enough data to decode '{}'. {} byte(s) would be required, but only {} byte(s) are available based on the {} ('{}' starts at overall parsed byte {}).", 98 self.layer.error_title(), 99 self.layer, 100 self.required_len, 101 self.len, 102 len_source, 103 self.layer, 104 self.layer_start_offset 105 ) 106 } else { 107 write!( 108 f, 109 "{}: Not enough data to decode '{}'. {} byte(s) would be required, but only {} byte(s) are available based on the {}.", 110 self.layer.error_title(), 111 self.layer, 112 self.required_len, 113 self.len, 114 len_source 115 ) 116 } 117 } else if self.layer_start_offset > 0 { 118 write!( 119 f, 120 "{}: Length of {} byte(s) is too big for an '{}' (maximum is {} bytes). The {} was used to determine the length ('{}' starts at overall parsed byte {}).", 121 self.layer.error_title(), 122 self.len, 123 self.layer, 124 self.required_len, 125 len_source, 126 self.layer, 127 self.layer_start_offset 128 ) 129 } else { 130 write!( 131 f, 132 "{}: Length of {} byte(s) is too big for an '{}' (maximum is {} bytes). The {} was used to determine the length.", 133 self.layer.error_title(), 134 self.len, 135 self.layer, 136 self.required_len, 137 len_source 138 ) 139 } 140 } 141 } 142 143 #[cfg(feature = "std")] 144 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 145 impl std::error::Error for LenError { source(&self) -> Option<&(dyn std::error::Error + 'static)>146 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 147 None 148 } 149 } 150 151 #[cfg(test)] 152 mod test { 153 use super::*; 154 use alloc::format; 155 use std::{ 156 collections::hash_map::DefaultHasher, 157 error::Error, 158 hash::{Hash, Hasher}, 159 }; 160 161 #[test] add_offset()162 fn add_offset() { 163 assert_eq!( 164 LenError { 165 required_len: 2, 166 layer: Layer::Icmpv4, 167 len: 1, 168 len_source: LenSource::Slice, 169 layer_start_offset: 20, 170 } 171 .add_offset(100), 172 LenError { 173 required_len: 2, 174 layer: Layer::Icmpv4, 175 len: 1, 176 len_source: LenSource::Slice, 177 layer_start_offset: 120, 178 } 179 ); 180 } 181 182 #[test] debug()183 fn debug() { 184 assert_eq!( 185 format!( 186 "{:?}", 187 LenError { 188 required_len: 2, 189 layer: Layer::Ipv4Header, 190 len: 1, 191 len_source: LenSource::Slice, 192 layer_start_offset: 0 193 } 194 ), 195 format!( 196 "LenError {{ required_len: {:?}, len: {:?}, len_source: {:?}, layer: {:?}, layer_start_offset: {:?} }}", 197 2, 1, LenSource::Slice, Layer::Ipv4Header, 0 198 ), 199 ); 200 } 201 202 #[test] clone_eq_hash()203 fn clone_eq_hash() { 204 let err = LenError { 205 required_len: 2, 206 layer: Layer::Icmpv4, 207 len: 1, 208 len_source: LenSource::Slice, 209 layer_start_offset: 20, 210 }; 211 assert_eq!(err, err.clone()); 212 let hash_a = { 213 let mut hasher = DefaultHasher::new(); 214 err.hash(&mut hasher); 215 hasher.finish() 216 }; 217 let hash_b = { 218 let mut hasher = DefaultHasher::new(); 219 err.clone().hash(&mut hasher); 220 hasher.finish() 221 }; 222 assert_eq!(hash_a, hash_b); 223 } 224 225 #[test] fmt()226 fn fmt() { 227 // len sources based tests (not enough data) 228 { 229 use crate::LenSource::*; 230 let len_source_tests = [ 231 (Slice, "IPv4 Header Error: Not enough data to decode 'IPv4 header'. 2 byte(s) would be required, but only 1 byte(s) are available based on the slice length."), 232 (Ipv4HeaderTotalLen, "IPv4 Header Error: Not enough data to decode 'IPv4 header'. 2 byte(s) would be required, but only 1 byte(s) are available based on the length calculated from the IPv4 header 'total length' field."), 233 (Ipv6HeaderPayloadLen, "IPv4 Header Error: Not enough data to decode 'IPv4 header'. 2 byte(s) would be required, but only 1 byte(s) are available based on the length calculated from the IPv6 header 'payload length' field."), 234 (UdpHeaderLen, "IPv4 Header Error: Not enough data to decode 'IPv4 header'. 2 byte(s) would be required, but only 1 byte(s) are available based on the length calculated from the UDP header 'length' field."), 235 (TcpHeaderLen, "IPv4 Header Error: Not enough data to decode 'IPv4 header'. 2 byte(s) would be required, but only 1 byte(s) are available based on the length calculated from the TCP header 'length' field."), 236 ]; 237 238 for test in len_source_tests { 239 assert_eq!( 240 test.1, 241 format!( 242 "{}", 243 LenError { 244 required_len: 2, 245 layer: Layer::Ipv4Header, 246 len: 1, 247 len_source: test.0, 248 layer_start_offset: 0 249 } 250 ) 251 ); 252 } 253 } 254 255 // start offset based test 256 assert_eq!( 257 "IPv4 Header Error: Not enough data to decode 'IPv4 header'. 2 byte(s) would be required, but only 1 byte(s) are available based on the slice length ('IPv4 header' starts at overall parsed byte 4).", 258 format!( 259 "{}", 260 LenError{ 261 required_len: 2, 262 len: 1, 263 len_source: LenSource::Slice, 264 layer: Layer::Ipv4Header, 265 layer_start_offset: 4 266 } 267 ) 268 ); 269 270 // len sources based tests (length too big) 271 { 272 use crate::LenSource::*; 273 let len_source_tests = [ 274 (Slice, "IPv4 Header Error: Length of 2 byte(s) is too big for an 'IPv4 header' (maximum is 1 bytes). The slice length was used to determine the length."), 275 (Ipv4HeaderTotalLen, "IPv4 Header Error: Length of 2 byte(s) is too big for an 'IPv4 header' (maximum is 1 bytes). The length calculated from the IPv4 header 'total length' field was used to determine the length."), 276 (Ipv6HeaderPayloadLen, "IPv4 Header Error: Length of 2 byte(s) is too big for an 'IPv4 header' (maximum is 1 bytes). The length calculated from the IPv6 header 'payload length' field was used to determine the length."), 277 (UdpHeaderLen, "IPv4 Header Error: Length of 2 byte(s) is too big for an 'IPv4 header' (maximum is 1 bytes). The length calculated from the UDP header 'length' field was used to determine the length."), 278 (TcpHeaderLen, "IPv4 Header Error: Length of 2 byte(s) is too big for an 'IPv4 header' (maximum is 1 bytes). The length calculated from the TCP header 'length' field was used to determine the length."), 279 ]; 280 281 for test in len_source_tests { 282 assert_eq!( 283 test.1, 284 format!( 285 "{}", 286 LenError { 287 required_len: 1, 288 layer: Layer::Ipv4Header, 289 len: 2, 290 len_source: test.0, 291 layer_start_offset: 0 292 } 293 ) 294 ); 295 } 296 } 297 298 // start offset based test 299 assert_eq!( 300 "IPv4 Header Error: Length of 2 byte(s) is too big for an 'IPv4 header' (maximum is 1 bytes). The slice length was used to determine the length ('IPv4 header' starts at overall parsed byte 4).", 301 format!( 302 "{}", 303 LenError{ 304 required_len: 1, 305 len: 2, 306 len_source: LenSource::Slice, 307 layer: Layer::Ipv4Header, 308 layer_start_offset: 4 309 } 310 ) 311 ); 312 } 313 314 #[cfg(feature = "std")] 315 #[test] source()316 fn source() { 317 assert!(LenError { 318 required_len: 0, 319 len: 0, 320 len_source: LenSource::Slice, 321 layer: Layer::Ipv4Header, 322 layer_start_offset: 0 323 } 324 .source() 325 .is_none()); 326 } 327 } 328