fix unrecoverable Err(Overflow) in websocket frame parser

This commit is contained in:
maotao 2022-06-22 15:45:34 +08:00
parent 265fa0d050
commit ca02dc4630
2 changed files with 31 additions and 15 deletions

View File

@ -1,7 +1,8 @@
# Changes
## Unreleased - 2021-xx-xx
### Fixed
- Websocket parser throw endless Overflow after received oversized frame.
## 3.1.0 - 2022-06-11
### Changed

View File

@ -17,7 +17,6 @@ impl Parser {
fn parse_metadata(
src: &[u8],
server: bool,
max_size: usize,
) -> Result<Option<(usize, bool, OpCode, usize, Option<[u8; 4]>)>, ProtocolError> {
let chunk_len = src.len();
@ -60,20 +59,12 @@ impl Parser {
return Ok(None);
}
let len = u64::from_be_bytes(TryFrom::try_from(&src[idx..idx + 8]).unwrap());
if len > max_size as u64 {
return Err(ProtocolError::Overflow);
}
idx += 8;
len as usize
} else {
len as usize
};
// check for max allowed size
if length > max_size {
return Err(ProtocolError::Overflow);
}
let mask = if server {
if chunk_len < idx + 4 {
return Ok(None);
@ -98,8 +89,7 @@ impl Parser {
max_size: usize,
) -> Result<Option<(bool, OpCode, Option<BytesMut>)>, ProtocolError> {
// try to parse ws frame metadata
let (idx, finished, opcode, length, mask) =
match Parser::parse_metadata(src, server, max_size)? {
let (idx, finished, opcode, length, mask) = match Parser::parse_metadata(src, server)? {
None => return Ok(None),
Some(res) => res,
};
@ -112,6 +102,12 @@ impl Parser {
// remove prefix
src.advance(idx);
// check for max allowed size
if length > max_size {
src.advance(length);
return Err(ProtocolError::Overflow);
}
// no need for body
if length == 0 {
return Ok(Some((finished, opcode, None)));
@ -339,6 +335,25 @@ mod tests {
}
}
#[test]
fn test_parse_frame_max_size_recoverability() {
let mut buf =
BytesMut::from(&[0b0000_0001u8, 0b0000_0010u8, 0b0000_0000u8, 0b0000_0000u8][..]);
buf.extend(&[0b0000_0010u8, 0b0000_0010u8, 0xffu8, 0xffu8]);
assert_eq!(buf.len(), 8);
if let Err(ProtocolError::Overflow) = Parser::parse(&mut buf, false, 1) {
} else {
unreachable!("error");
}
assert_eq!(buf.len(), 4);
let frame = extract(Parser::parse(&mut buf, false, 2));
assert!(!frame.finished);
assert_eq!(frame.opcode, OpCode::Binary);
assert_eq!(frame.payload, Bytes::from(vec![0xffu8, 0xffu8]));
assert_eq!(buf.len(), 0);
}
#[test]
fn test_ping_frame() {
let mut buf = BytesMut::new();