Skip to content

Commit 941dadc

Browse files
committed
return ReadDirParseError for malformed responses
1 parent c63c420 commit 941dadc

File tree

1 file changed

+67
-93
lines changed

1 file changed

+67
-93
lines changed

src/proto/network/pxe.rs

+67-93
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,8 @@ impl BaseCode {
232232
server_ip: &IpAddress,
233233
directory_name: &CStr8,
234234
buffer: &'a mut [u8],
235-
) -> Result<impl Iterator<Item = TftpFileInfo<'a>> + 'a> {
235+
) -> Result<impl Iterator<Item = core::result::Result<TftpFileInfo<'a>, ReadDirParseError>> + 'a>
236+
{
236237
let filename = NonNull::from(&directory_name.to_bytes_with_nul()[0]).cast();
237238

238239
let buffer_ptr = NonNull::from(&buffer[0]).cast();
@@ -258,52 +259,37 @@ impl BaseCode {
258259
let buffer = &buffer[..buffer_size];
259260

260261
let mut iterator = buffer.split_inclusive(|b| *b == 0);
261-
262-
Ok(from_fn(move || {
263-
let filename = iterator
264-
.next()
265-
.expect("the final entry should have an empty file name");
262+
let mut parse_next = move || {
263+
let filename = iterator.next().ok_or(ReadDirParseError)?;
266264
if filename == [0] {
267265
// This is the final entry.
268-
return None;
266+
return Ok(None);
269267
}
270268
let filename = CStr8::from_bytes_with_nul(filename).unwrap();
271269

272-
let information_string = iterator
273-
.next()
274-
.expect("each file should have an information string");
270+
let information_string = iterator.next().ok_or(ReadDirParseError)?;
275271
let (_null_terminator, information_string) = information_string.split_last().unwrap();
276-
let information_string = core::str::from_utf8(information_string)
277-
.expect("the information string should be valid utf-8");
272+
let information_string =
273+
core::str::from_utf8(information_string).map_err(|_| ReadDirParseError)?;
278274

279275
let (size, rest) = information_string
280276
.split_once(' ')
281-
.expect("the information string should be valid");
282-
let (year, rest) = rest
283-
.split_once('-')
284-
.expect("the information string should be valid");
285-
let (month, rest) = rest
286-
.split_once('-')
287-
.expect("the information string should be valid");
288-
let (day, rest) = rest
289-
.split_once(' ')
290-
.expect("the information string should be valid");
291-
let (hour, rest) = rest
292-
.split_once(':')
293-
.expect("the information string should be valid");
294-
let (minute, second) = rest
295-
.split_once(':')
296-
.expect("the information string should be valid");
297-
298-
let size = size.parse().expect("size should be a number");
299-
let year = year.parse().expect("year should be a number");
300-
let month = month.parse().expect("month should be a number");
301-
let day = day.parse().expect("day should be a number");
302-
let hour = hour.parse().expect("hour should be a number");
303-
let minute = minute.parse().expect("minute should be a number");
304-
let second = second.parse().expect("second should be a number");
305-
306-
Some(TftpFileInfo {
277+
.ok_or(ReadDirParseError)?;
278+
let (year, rest) = rest.split_once('-').ok_or(ReadDirParseError)?;
279+
let (month, rest) = rest.split_once('-').ok_or(ReadDirParseError)?;
280+
let (day, rest) = rest.split_once(' ').ok_or(ReadDirParseError)?;
281+
let (hour, rest) = rest.split_once(':').ok_or(ReadDirParseError)?;
282+
let (minute, second) = rest.split_once(':').ok_or(ReadDirParseError)?;
283+
284+
let size = size.parse().map_err(|_| ReadDirParseError)?;
285+
let year = year.parse().map_err(|_| ReadDirParseError)?;
286+
let month = month.parse().map_err(|_| ReadDirParseError)?;
287+
let day = day.parse().map_err(|_| ReadDirParseError)?;
288+
let hour = hour.parse().map_err(|_| ReadDirParseError)?;
289+
let minute = minute.parse().map_err(|_| ReadDirParseError)?;
290+
let second = second.parse().map_err(|_| ReadDirParseError)?;
291+
292+
Ok(Some(TftpFileInfo {
307293
filename,
308294
size,
309295
year,
@@ -312,9 +298,9 @@ impl BaseCode {
312298
hour,
313299
minute,
314300
second,
315-
})
316-
})
317-
.fuse())
301+
}))
302+
};
303+
Ok(from_fn(move || parse_next().transpose()).fuse())
318304
}
319305

320306
/// Returns the size of a file located on a MTFTP server.
@@ -389,7 +375,8 @@ impl BaseCode {
389375
server_ip: &IpAddress,
390376
buffer: &'a mut [u8],
391377
info: &MtftpInfo,
392-
) -> Result<impl Iterator<Item = MtftpFileInfo<'a>> + 'a> {
378+
) -> Result<impl Iterator<Item = core::result::Result<MtftpFileInfo<'a>, ReadDirParseError>> + 'a>
379+
{
393380
let buffer_ptr = NonNull::from(&buffer[0]).cast();
394381
let mut buffer_size = u64::try_from(buffer.len()).expect("buffer length should fit in u64");
395382

@@ -413,71 +400,53 @@ impl BaseCode {
413400
let buffer = &buffer[..buffer_size];
414401

415402
let mut iterator = buffer.split_inclusive(|b| *b == 0);
416-
417-
Ok(from_fn(move || {
418-
let filename = iterator
419-
.next()
420-
.expect("the final entry should have an empty file name");
403+
let mut parse_next = move || {
404+
let filename = iterator.next().ok_or(ReadDirParseError)?;
421405
if filename == [0] {
422406
// This is the final entry.
423-
return None;
407+
return Ok(None);
424408
}
425409
let filename = CStr8::from_bytes_with_nul(filename).unwrap();
426410

427-
let multicast_ip = iterator
428-
.next()
429-
.expect("each file should have a multicast ip address");
411+
let multicast_ip = iterator.next().ok_or(ReadDirParseError)?;
430412
let (_null_terminator, multicast_ip) = multicast_ip.split_last().unwrap();
431-
let multicast_ip = core::str::from_utf8(multicast_ip)
432-
.expect("the multicast ip address should be valid utf-8");
413+
let multicast_ip = core::str::from_utf8(multicast_ip).map_err(|_| ReadDirParseError)?;
433414
let mut octets = multicast_ip.split('.');
434415
let mut buffer = [0; 4];
435416
for b in buffer.iter_mut() {
436-
let octet = octets
437-
.next()
438-
.expect("the information string should be valid");
439-
let octet = octet
440-
.parse()
441-
.expect("each octet in the ip address should be a number");
417+
let octet = octets.next().ok_or(ReadDirParseError)?;
418+
let octet = octet.parse().map_err(|_| ReadDirParseError)?;
442419
*b = octet;
443420
}
421+
if octets.next().is_some() {
422+
// The ip should have exact 4 octets, not more.
423+
return Err(ReadDirParseError);
424+
}
444425
let ip_address = IpAddress::new_v4(buffer);
445426

446-
let information_string = iterator
447-
.next()
448-
.expect("each file should have an information string");
427+
let information_string = iterator.next().ok_or(ReadDirParseError)?;
449428
let (_null_terminator, information_string) = information_string.split_last().unwrap();
450-
let information_string = core::str::from_utf8(information_string)
451-
.expect("the information string should be valid utf-8");
429+
let information_string =
430+
core::str::from_utf8(information_string).map_err(|_| ReadDirParseError)?;
452431

453432
let (size, rest) = information_string
454433
.split_once(' ')
455-
.expect("the information string should be valid");
456-
let (year, rest) = rest
457-
.split_once('-')
458-
.expect("the information string should be valid");
459-
let (month, rest) = rest
460-
.split_once('-')
461-
.expect("the information string should be valid");
462-
let (day, rest) = rest
463-
.split_once(' ')
464-
.expect("the information string should be valid");
465-
let (hour, rest) = rest
466-
.split_once(':')
467-
.expect("the information string should be valid");
468-
let (minute, second) = rest
469-
.split_once(':')
470-
.expect("the information string should be valid");
471-
472-
let size = size.parse().expect("size should be a number");
473-
let year = year.parse().expect("year should be a number");
474-
let month = month.parse().expect("month should be a number");
475-
let day = day.parse().expect("day should be a number");
476-
let hour = hour.parse().expect("hour should be a number");
477-
let minute = minute.parse().expect("minute should be a number");
478-
let second = second.parse().expect("second should be a number");
479-
480-
Some(MtftpFileInfo {
434+
.ok_or(ReadDirParseError)?;
435+
let (year, rest) = rest.split_once('-').ok_or(ReadDirParseError)?;
436+
let (month, rest) = rest.split_once('-').ok_or(ReadDirParseError)?;
437+
let (day, rest) = rest.split_once(' ').ok_or(ReadDirParseError)?;
438+
let (hour, rest) = rest.split_once(':').ok_or(ReadDirParseError)?;
439+
let (minute, second) = rest.split_once(':').ok_or(ReadDirParseError)?;
440+
441+
let size = size.parse().map_err(|_| ReadDirParseError)?;
442+
let year = year.parse().map_err(|_| ReadDirParseError)?;
443+
let month = month.parse().map_err(|_| ReadDirParseError)?;
444+
let day = day.parse().map_err(|_| ReadDirParseError)?;
445+
let hour = hour.parse().map_err(|_| ReadDirParseError)?;
446+
let minute = minute.parse().map_err(|_| ReadDirParseError)?;
447+
let second = second.parse().map_err(|_| ReadDirParseError)?;
448+
449+
Ok(Some(MtftpFileInfo {
481450
filename,
482451
ip_address,
483452
size,
@@ -487,9 +456,9 @@ impl BaseCode {
487456
hour,
488457
minute,
489458
second,
490-
})
491-
})
492-
.fuse())
459+
}))
460+
};
461+
Ok(from_fn(move || parse_next().transpose()).fuse())
493462
}
494463

495464
/// Writes a UDP packet to the network interface.
@@ -1274,3 +1243,8 @@ pub struct MtftpFileInfo<'a> {
12741243
pub minute: u8,
12751244
pub second: f32,
12761245
}
1246+
1247+
/// Returned if a server sends a malformed response in
1248+
/// [`BaseCode::tftp_read_dir`] or [`BaseCode::mtftp_read_dir`].
1249+
#[derive(Clone, Copy, Debug)]
1250+
pub struct ReadDirParseError;

0 commit comments

Comments
 (0)