From 01ce5b1ed3c6b5e3feb319a8733d6e9e1fb9e9b0 Mon Sep 17 00:00:00 2001 From: Alex Helfet Date: Wed, 27 Dec 2017 19:57:28 +0000 Subject: [PATCH] New error variant: EofBeforeFrame. This is half the fix for #12. --- framed/src/error.rs | 6 +++++- framed/src/lib.rs | 41 +++++++++++++++++++++++++++++++++-------- framed/src/typed.rs | 2 +- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/framed/src/error.rs b/framed/src/error.rs index b3ccef1..168abeb 100644 --- a/framed/src/error.rs +++ b/framed/src/error.rs @@ -20,9 +20,13 @@ pub enum Error { /// COBS decode failed CobsDecodeFailed, - /// End of data while reading a frame + /// End of data while reading a frame; we received some of a frame + /// but it was incomplete. EofDuringFrame, + /// End of data before a frame started; we received none of a frame. + EofBeforeFrame, + /// The supplied value was too short to be an encoded frame EncodedFrameTooShort, diff --git a/framed/src/lib.rs b/framed/src/lib.rs index d74b665..24be039 100644 --- a/framed/src/lib.rs +++ b/framed/src/lib.rs @@ -240,9 +240,11 @@ pub fn encode_to_writer(p: &Payload, w: &mut W) -> Result { /// /// # Errors /// -/// Returns `Err(Error::EofDuringFrame` if `e` is not a complete -/// encoded frame, which should have `FRAME_END_SYMBOL` as the last -/// byte. +/// Returns `Err(Error::EofDuringFrame`) if `e` contains >= 1 bytes of +/// a frame, but not a complete frame. A complete frame should have +/// `FRAME_END_SYMBOL` as the last byte. +/// +/// Returns `Err(Error::EofBeforeFrame`) if `e.len()` is 0. /// /// # Panics /// @@ -250,17 +252,21 @@ pub fn encode_to_writer(p: &Payload, w: &mut W) -> Result { /// Ensure `dest.len() >= max_decoded_len(e.len())?`. pub fn decode_to_slice(e: &Encoded, mut dest: &mut [u8]) -> Result { - assert!(dest.len() >= max_decoded_len(e.len())?); - #[cfg(feature = "trace")] { println!("framed: Encoded input = {:?}", e); } + if e.len() == 0 { + return Err(Error::EofBeforeFrame); + } + if e[e.len()-1] != FRAME_END_SYMBOL { return Err(Error::EofDuringFrame) } + assert!(dest.len() >= max_decoded_len(e.len())?); assert_eq!(e[e.len() - 1], FRAME_END_SYMBOL); + // Just the body (COBS-encoded payload). let body = &e[0..(e.len()-1)]; @@ -280,6 +286,9 @@ pub fn decode_to_slice(e: &Encoded, mut dest: &mut [u8]) /// Decode the supplied encoded frame, returning the payload on the heap. #[cfg(feature = "use_std")] pub fn decode_to_box(e: &Encoded) -> Result { + if e.len() == 0 { + return Err(Error::EofBeforeFrame); + } let mut buf = vec![0; max_decoded_len(e.len())?]; let len = decode_to_slice(e, &mut buf)?; buf.truncate(len); @@ -299,12 +308,16 @@ pub fn decode_from_reader(r: &mut Read) -> Result { println!("framed: Read result = {:?}", res); } match res { + // In the 2 EOF cases defer to decode_to_box to return the + // correct error (EofBeforeFrame or EofDuringFrame). Err(ref e) if e.kind() == io::ErrorKind::UnexpectedEof => - return Err(Error::EofDuringFrame), + return decode_to_box(&*next_frame), Ok(0) => - return Err(Error::EofDuringFrame), + return decode_to_box(&*next_frame), + Err(e) => return Err(Error::from(e)), - Ok(_) => (), + Ok(1) => (), + Ok(_) => unreachable!(), }; #[cfg(feature = "trace")] { @@ -510,6 +523,18 @@ mod rw_tests { #[test] fn empty_input() { let (mut _tx, mut rx) = pair(); + match rx.recv() { + Err(Error::EofBeforeFrame) => (), + e @ _ => panic!("Bad value: {:?}", e) + } + } + + #[test] + fn partial_input() { + let c = Channel::new(); + let mut rx = Receiver::new(Box::new(c.reader()) as Box); + let mut tx_raw = c.writer(); + tx_raw.write(&[0x01]).unwrap(); match rx.recv() { Err(Error::EofDuringFrame) => (), e @ _ => panic!("Bad value: {:?}", e) diff --git a/framed/src/typed.rs b/framed/src/typed.rs index f9aeb86..11cfa7b 100644 --- a/framed/src/typed.rs +++ b/framed/src/typed.rs @@ -170,7 +170,7 @@ mod tests { fn empty_input() { let (mut _tx, mut rx) = pair(); match rx.recv() { - Err(Error::EofDuringFrame) => (), + Err(Error::EofBeforeFrame) => (), e @ _ => panic!("Bad value: {:?}", e) } }