Skip to content

Commit

Permalink
Handle missing \r\n with connection close
Browse files Browse the repository at this point in the history
  • Loading branch information
algesten committed Jul 4, 2024
1 parent 96061c6 commit 42bffb7
Showing 1 changed file with 53 additions and 2 deletions.
55 changes: 53 additions & 2 deletions src/chunked/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,39 @@ where
_ => Err(IoError::new(ErrorKind::InvalidInput, DecoderError)),
}
}

// Sometimes the last \r\n is missing.
fn read_end(&mut self) -> IoResult<()> {
fn expect_or_end(
bytes: &mut impl Iterator<Item = IoResult<u8>>,
expected: u8,
) -> IoResult<()> {
match bytes.next() {
Some(Ok(c)) => {
if c == expected {
Ok(())
} else {
Err(IoError::new(ErrorKind::InvalidInput, DecoderError))
}
}
Some(Err(e)) => {
match e.kind() {
// Closed connections are ok.
ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted => Ok(()),
_ => Err(IoError::new(ErrorKind::InvalidInput, DecoderError)),
}
}
None => Ok(()), // End of iterator is ok
}
}

let mut bytes = self.source.by_ref().bytes();

expect_or_end(&mut bytes, b'\r')?;
expect_or_end(&mut bytes, b'\n')?;

Ok(())
}
}

impl<R> Read for Decoder<R>
Expand All @@ -125,8 +158,7 @@ where

// if the chunk size is 0, we are at EOF
if chunk_size == 0 {
self.read_carriage_return()?;
self.read_line_feed()?;
self.read_end()?;
return Ok(0);
}

Expand Down Expand Up @@ -287,4 +319,23 @@ mod test {
let mut string = String::new();
assert!(decoded.read_to_string(&mut string).is_err());
}

#[test]
fn test_decode_end_missing_last_crlf() {
// This has been observed in the wild.
// See https://github.com/algesten/ureq/issues/325

// Missing last \r\n
let source = io::Cursor::new(
"3\r\nhel\r\nb\r\nlo world!!!\r\n0\r\n"
.to_string()
.into_bytes(),
);
let mut decoded = Decoder::new(source);

let mut string = String::new();
decoded.read_to_string(&mut string).unwrap();

assert_eq!(string, "hello world!!!");
}
}

0 comments on commit 42bffb7

Please sign in to comment.