@@ -42,7 +42,8 @@ pub enum EthError {
42
42
43
43
impl Eth {
44
44
/// The length (in bytes) of an [`Eth`] header
45
- pub const HEADER_LEN : usize = 14 ;
45
+ #[ allow( clippy:: unwrap_used) ] // trivially safe const eval
46
+ pub const HEADER_LEN : NonZero < u16 > = NonZero :: new ( 14 ) . unwrap ( ) ;
46
47
47
48
/// Create a new [Eth] header.
48
49
#[ must_use]
@@ -100,7 +101,10 @@ impl Eth {
100
101
impl Parse for Eth {
101
102
type Error = EthError ;
102
103
103
- fn parse ( buf : & [ u8 ] ) -> Result < ( Self , NonZero < usize > ) , ParseError < Self :: Error > > {
104
+ fn parse ( buf : & [ u8 ] ) -> Result < ( Self , NonZero < u16 > ) , ParseError < Self :: Error > > {
105
+ if buf. len ( ) > u16:: MAX as usize {
106
+ return Err ( ParseError :: BufferTooLong ( buf. len ( ) ) ) ;
107
+ }
104
108
let ( inner, rest) = Ethernet2Header :: from_slice ( buf) . map_err ( |e| {
105
109
let expected = NonZero :: new ( e. required_len ) . unwrap_or_else ( || unreachable ! ( ) ) ;
106
110
ParseError :: Length ( LengthError {
@@ -114,7 +118,9 @@ impl Parse for Eth {
114
118
rest = rest. len( ) ,
115
119
buf = buf. len( )
116
120
) ;
117
- let consumed = NonZero :: new ( buf. len ( ) - rest. len ( ) ) . ok_or_else ( || unreachable ! ( ) ) ?;
121
+ #[ allow( clippy:: cast_possible_truncation) ] // buffer length bounded above
122
+ let consumed =
123
+ NonZero :: new ( ( buf. len ( ) - rest. len ( ) ) as u16 ) . ok_or_else ( || unreachable ! ( ) ) ?;
118
124
let new = Self ( inner) ;
119
125
// integrity check for ethernet header
120
126
new. destination ( )
@@ -132,12 +138,16 @@ impl Parse for Eth {
132
138
impl DeParse for Eth {
133
139
type Error = ( ) ;
134
140
135
- fn size ( & self ) -> NonZero < usize > {
136
- NonZero :: new ( self . 0 . header_len ( ) ) . unwrap_or_else ( || unreachable ! ( ) )
141
+ fn size ( & self ) -> NonZero < u16 > {
142
+ #[ allow( clippy:: cast_possible_truncation) ] // Eth headers have fixed length
143
+ NonZero :: new ( self . 0 . header_len ( ) as u16 ) . unwrap_or_else ( || unreachable ! ( ) )
137
144
}
138
145
139
- fn deparse ( & self , buf : & mut [ u8 ] ) -> Result < NonZero < usize > , DeParseError < Self :: Error > > {
146
+ fn deparse ( & self , buf : & mut [ u8 ] ) -> Result < NonZero < u16 > , DeParseError < Self :: Error > > {
140
147
let len = buf. len ( ) ;
148
+ if buf. len ( ) > u16:: MAX as usize {
149
+ return Err ( DeParseError :: BufferTooLong ( len) ) ;
150
+ }
141
151
let unused = self . 0 . write_to_slice ( buf) . map_err ( |e| {
142
152
let expected = NonZero :: new ( e. required_len ) . unwrap_or_else ( || unreachable ! ( ) ) ;
143
153
DeParseError :: Length ( LengthError {
@@ -150,7 +160,8 @@ impl DeParse for Eth {
150
160
"unused.len() >= buf.len() ({unused} >= {len})" ,
151
161
unused = unused. len( ) ,
152
162
) ;
153
- let consumed = NonZero :: new ( len - unused. len ( ) ) . ok_or_else ( || unreachable ! ( ) ) ?;
163
+ #[ allow( clippy:: cast_possible_truncation) ] // buffer len upper bounded already
164
+ let consumed = NonZero :: new ( ( len - unused. len ( ) ) as u16 ) . ok_or_else ( || unreachable ! ( ) ) ?;
154
165
Ok ( consumed)
155
166
}
156
167
}
@@ -231,75 +242,79 @@ mod contract {
231
242
#[ allow( clippy:: unwrap_used, clippy:: expect_used) ] // valid in test code for unreachable cases
232
243
#[ cfg( test) ]
233
244
mod test {
245
+ const HEADER_LEN_USIZE : usize = Eth :: HEADER_LEN . get ( ) as usize ;
234
246
use crate :: eth:: { DestinationMacAddressError , Eth , EthError , SourceMacAddressError } ;
235
- use crate :: parse:: { DeParse , Parse , ParseError } ;
247
+ use crate :: parse:: { DeParse , IntoNonZeroUSize , Parse , ParseError } ;
236
248
237
249
#[ test]
238
250
fn parse_back ( ) {
239
251
bolero:: check!( ) . with_type ( ) . for_each ( |eth : & Eth | {
240
252
assert ! ( eth. source( ) . inner( ) . valid_src( ) . is_ok( ) ) ;
241
253
assert ! ( eth. destination( ) . inner( ) . valid_dst( ) . is_ok( ) ) ;
242
- let mut buf = [ 0u8 ; Eth :: HEADER_LEN ] ;
254
+ let mut buf = [ 0u8 ; HEADER_LEN_USIZE ] ;
243
255
eth. deparse ( & mut buf) . unwrap ( ) ;
244
256
let ( eth2, consumed) = Eth :: parse ( & buf) . unwrap ( ) ;
245
257
assert_eq ! ( eth, & eth2) ;
246
- assert_eq ! ( consumed. get ( ) , Eth :: HEADER_LEN ) ;
258
+ assert_eq ! ( consumed, Eth :: HEADER_LEN ) ;
247
259
} ) ;
248
260
}
249
261
250
262
fn parse_buffer_of_fixed_length < const LEN : usize > ( buf : & [ u8 ; LEN ] ) {
251
263
let outcome = Eth :: parse ( buf) ;
252
264
match outcome {
253
265
Ok ( ( eth, consumed) ) => {
254
- assert ! ( buf. len( ) >= Eth :: HEADER_LEN ) ;
255
- assert_eq ! ( consumed. get ( ) , Eth :: HEADER_LEN ) ;
266
+ assert ! ( buf. len( ) >= Eth :: HEADER_LEN . into_non_zero_usize ( ) . get ( ) ) ;
267
+ assert_eq ! ( consumed, Eth :: HEADER_LEN ) ;
256
268
assert ! ( eth. source( ) . inner( ) . valid_src( ) . is_ok( ) ) ;
257
269
assert ! ( eth. destination( ) . inner( ) . valid_dst( ) . is_ok( ) ) ;
258
- let mut buf2 = [ 0u8 ; 14 ] ;
270
+ let mut buf2 = [ 0u8 ; HEADER_LEN_USIZE ] ;
259
271
eth. deparse ( & mut buf2) . unwrap ( ) ;
260
272
let ( eth2, consumed2) = Eth :: parse ( & buf2) . unwrap ( ) ;
261
273
assert_eq ! ( eth, eth2) ;
262
- assert_eq ! ( consumed2. get ( ) , Eth :: HEADER_LEN ) ;
274
+ assert_eq ! ( consumed2, Eth :: HEADER_LEN ) ;
263
275
}
264
276
Err ( ParseError :: Length ( e) ) => {
265
- assert_eq ! ( e. expected. get ( ) , Eth :: HEADER_LEN ) ;
277
+ assert_eq ! ( e. expected, Eth :: HEADER_LEN . into_non_zero_usize ( ) ) ;
266
278
assert_eq ! ( e. actual, buf. len( ) ) ;
267
- assert ! ( buf. len( ) < Eth :: HEADER_LEN ) ;
279
+ assert ! ( buf. len( ) < Eth :: HEADER_LEN . into_non_zero_usize ( ) . get ( ) ) ;
268
280
}
269
281
Err ( ParseError :: Invalid (
270
282
EthError :: InvalidDestination ( DestinationMacAddressError :: ZeroDestination ( z) )
271
283
| EthError :: InvalidSource ( SourceMacAddressError :: ZeroSource ( z) ) ,
272
284
) ) => {
273
- assert ! ( buf. len( ) >= Eth :: HEADER_LEN ) ;
285
+ assert ! ( buf. len( ) >= Eth :: HEADER_LEN . into_non_zero_usize ( ) . get ( ) ) ;
274
286
assert ! ( z. is_zero( ) ) ;
275
287
}
276
288
Err ( ParseError :: Invalid ( EthError :: InvalidSource (
277
289
SourceMacAddressError :: MulticastSource ( m) ,
278
290
) ) ) => {
279
- assert ! ( buf. len( ) >= Eth :: HEADER_LEN ) ;
291
+ assert ! ( buf. len( ) >= Eth :: HEADER_LEN . into_non_zero_usize ( ) . get ( ) ) ;
280
292
assert ! ( m. is_multicast( ) ) ;
281
293
}
294
+ Err ( ParseError :: BufferTooLong ( e) ) => {
295
+ assert_eq ! ( e, buf. len( ) ) ;
296
+ }
282
297
}
283
298
}
284
299
285
300
#[ test]
286
301
fn parse_arbitrary_bytes ( ) {
287
302
bolero:: check!( )
288
303
. with_type ( )
289
- . for_each ( parse_buffer_of_fixed_length :: < { Eth :: HEADER_LEN } > ) ;
304
+ . for_each ( parse_buffer_of_fixed_length :: < { HEADER_LEN_USIZE } > ) ;
290
305
}
291
306
292
307
#[ test]
293
308
fn parse_prop_test_buffer_too_short ( ) {
294
309
bolero:: check!( )
295
310
. with_type ( )
296
- . for_each ( parse_buffer_of_fixed_length :: < { Eth :: HEADER_LEN - 1 } > ) ;
311
+ . for_each ( parse_buffer_of_fixed_length :: < { HEADER_LEN_USIZE - 1 } > ) ;
297
312
}
298
313
299
314
#[ test]
300
315
fn parse_prop_test_excess_buffer ( ) {
301
316
bolero:: check!( )
302
317
. with_type ( )
303
- . for_each ( parse_buffer_of_fixed_length :: < { Eth :: HEADER_LEN + 1 } > ) ;
318
+ . for_each ( parse_buffer_of_fixed_length :: < { HEADER_LEN_USIZE + 1 } > ) ;
304
319
}
305
320
}
0 commit comments