Skip to content

Commit 0ebbc48

Browse files
committed
Add length check for frames.
1 parent 50bdcd1 commit 0ebbc48

18 files changed

+186
-75
lines changed

rsocket-test/tests/test_composite_metadata.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
use bytes::BytesMut;
1+
use bytes::{BufMut, BytesMut};
22
use rsocket_rust::extension::{self, CompositeMetadata, CompositeMetadataEntry, MimeType};
33
use rsocket_rust::utils::Writeable;
44

55
#[test]
6-
fn encode_and_decode_composite_metadata() {
6+
fn test_encode_and_decode() {
77
let bingo = |metadatas: Vec<&CompositeMetadataEntry>| {
88
assert_eq!(2, metadatas.len());
99
assert_eq!(
@@ -29,3 +29,13 @@ fn encode_and_decode_composite_metadata() {
2929
let cm2 = CompositeMetadata::decode(&mut bf).unwrap();
3030
bingo(cm2.iter().collect());
3131
}
32+
33+
#[test]
34+
fn test_bad() {
35+
let mut bf = BytesMut::new();
36+
bf.put_slice(b"must bad");
37+
assert!(
38+
CompositeMetadata::decode(&mut bf).is_err(),
39+
"should be error"
40+
)
41+
}

rsocket-test/tests/test_mimes.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@ extern crate rsocket_rust;
22

33
use rsocket_rust::extension::{self, MimeType};
44

5+
#[test]
6+
fn test_from_str() {
7+
let result = MimeType::from("foobar");
8+
match result {
9+
MimeType::WellKnown(_) => panic!("failed"),
10+
MimeType::Normal(s) => assert_eq!(&s, "foobar"),
11+
}
12+
}
13+
514
#[test]
615
fn test_wellknown() {
716
let well = MimeType::from("application/json");
@@ -10,3 +19,20 @@ fn test_wellknown() {
1019
let custom = MimeType::from("application/custom");
1120
assert_eq!(MimeType::Normal("application/custom".to_owned()), custom);
1221
}
22+
23+
#[test]
24+
fn test_parse() {
25+
assert!(MimeType::parse(0xFF).is_none(), "should be none");
26+
for x in 0..0x29 {
27+
assert!(MimeType::parse(x).is_some(), "should not be none");
28+
}
29+
for x in 0x29..0x7A {
30+
assert!(MimeType::parse(x).is_none(), "should be none");
31+
}
32+
for x in 0x7A..0x80 {
33+
assert!(MimeType::parse(x).is_some(), "should not be none");
34+
}
35+
for x in 0x80..0xFF {
36+
assert!(MimeType::parse(x).is_none(), "should be none");
37+
}
38+
}

rsocket/src/error.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub enum ErrorKind {
1919
WithDescription(String),
2020
IO(io::Error),
2121
Cancelled(),
22+
LengthTooShort(usize),
2223
}
2324

2425
#[derive(Debug)]
@@ -35,6 +36,7 @@ impl fmt::Display for RSocketError {
3536
ErrorKind::WithDescription(s) => write!(f, "{}", s),
3637
ErrorKind::IO(e) => write!(f, "{}", e),
3738
ErrorKind::Cancelled() => write!(f, "ERROR(CANCELLED)"),
39+
ErrorKind::LengthTooShort(n) => write!(f, "ERROR(MINIMAL LENGTH {})", n),
3840
}
3941
}
4042
}

rsocket/src/extension/mime.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@ lazy_static! {
1616
}
1717
m
1818
};
19-
}
20-
21-
lazy_static! {
2219
static ref STR_TO_U8: HashMap<&'static str, u8> = {
2320
let mut m = HashMap::new();
2421
for it in list_all().iter() {
@@ -58,7 +55,7 @@ impl AsRef<str> for MimeType {
5855

5956
impl From<&str> for MimeType {
6057
fn from(value: &str) -> MimeType {
61-
match STR_TO_U8.get(&value) {
58+
match STR_TO_U8.get(value) {
6259
Some(v) => Self::WellKnown(*v),
6360
None => Self::Normal(value.to_owned()),
6461
}

rsocket/src/frame/error.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use super::utils::too_short;
12
use super::{Body, Frame};
23
use crate::utils::{RSocketResult, Writeable};
34
use bytes::{Buf, BufMut, Bytes, BytesMut};
@@ -44,13 +45,17 @@ impl ErrorBuilder {
4445

4546
impl Error {
4647
pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult<Error> {
47-
let code = bf.get_u32();
48-
let d: Option<Bytes> = if !bf.is_empty() {
49-
Some(bf.to_bytes())
48+
if bf.len() < 4 {
49+
too_short(4)
5050
} else {
51-
None
52-
};
53-
Ok(Error { code, data: d })
51+
let code = bf.get_u32();
52+
let data: Option<Bytes> = if !bf.is_empty() {
53+
Some(bf.to_bytes())
54+
} else {
55+
None
56+
};
57+
Ok(Error { code, data })
58+
}
5459
}
5560

5661
pub fn builder(stream_id: u32, flag: u16) -> ErrorBuilder {

rsocket/src/frame/keepalive.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use super::utils::too_short;
12
use super::{Body, Frame};
23
use crate::utils::{RSocketResult, Writeable};
34
use bytes::{Buf, BufMut, Bytes, BytesMut};
@@ -43,14 +44,18 @@ impl KeepaliveBuilder {
4344

4445
impl Keepalive {
4546
pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult<Keepalive> {
46-
let position = bf.get_u64();
47-
let mut d: Option<Bytes> = None;
48-
if !bf.is_empty() {
49-
d = Some(bf.to_bytes());
47+
if bf.len() < 8 {
48+
return too_short(8);
5049
}
50+
let position = bf.get_u64();
51+
let data = if bf.is_empty() {
52+
None
53+
} else {
54+
Some(bf.to_bytes())
55+
};
5156
Ok(Keepalive {
5257
last_received_position: position,
53-
data: d,
58+
data,
5459
})
5560
}
5661

rsocket/src/frame/lease.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use super::utils::too_short;
12
use super::{Body, Frame};
23
use crate::utils::{RSocketResult, Writeable};
34
use bytes::{Buf, BufMut, Bytes, BytesMut};
@@ -51,6 +52,9 @@ impl LeaseBuilder {
5152

5253
impl Lease {
5354
pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult<Lease> {
55+
if bf.len() < 8 {
56+
return too_short(8);
57+
}
5458
let ttl = bf.get_u32();
5559
let n = bf.get_u32();
5660
let m = if flag & Frame::FLAG_METADATA != 0 {

rsocket/src/frame/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::error::RSocketError;
1+
use crate::error::{ErrorKind, RSocketError};
22
use crate::utils::{RSocketResult, Writeable};
33
use bytes::{Buf, BufMut, Bytes, BytesMut};
44

@@ -145,7 +145,9 @@ impl Frame {
145145
}
146146

147147
pub fn decode(b: &mut BytesMut) -> RSocketResult<Frame> {
148-
// TODO: check size
148+
if b.len() < LEN_HEADER {
149+
return Err(ErrorKind::LengthTooShort(LEN_HEADER).into());
150+
}
149151
let sid = b.get_u32();
150152
let n = b.get_u16();
151153
let (flag, kind) = (n & 0x03FF, (n & 0xFC00) >> 10);

rsocket/src/frame/payload.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use super::utils::{read_payload, too_short};
12
use super::{Body, Frame, PayloadSupport};
23
use crate::utils::{RSocketResult, Writeable};
34
use bytes::{BufMut, Bytes, BytesMut};
@@ -59,11 +60,7 @@ impl PayloadBuilder {
5960

6061
impl Payload {
6162
pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult<Payload> {
62-
let (m, d) = PayloadSupport::read(flag, bf);
63-
Ok(Payload {
64-
metadata: m,
65-
data: d,
66-
})
63+
read_payload(flag, bf).map(|(metadata, data)| Payload { metadata, data })
6764
}
6865

6966
pub fn builder(stream_id: u32, flag: u16) -> PayloadBuilder {

rsocket/src/frame/request_channel.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use super::utils::{read_payload, too_short};
12
use super::{Body, Frame, PayloadSupport, REQUEST_MAX};
23
use crate::utils::{RSocketResult, Writeable};
34
use bytes::{Buf, BufMut, Bytes, BytesMut};
@@ -66,13 +67,16 @@ impl RequestChannelBuilder {
6667

6768
impl RequestChannel {
6869
pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult<RequestChannel> {
69-
let n = bf.get_u32();
70-
let (m, d) = PayloadSupport::read(flag, bf);
71-
Ok(RequestChannel {
72-
initial_request_n: n,
73-
metadata: m,
74-
data: d,
75-
})
70+
if bf.len() < 4 {
71+
too_short(4)
72+
} else {
73+
let initial_request_n = bf.get_u32();
74+
read_payload(flag, bf).map(move |(metadata, data)| RequestChannel {
75+
initial_request_n,
76+
metadata,
77+
data,
78+
})
79+
}
7680
}
7781

7882
pub fn builder(stream_id: u32, flag: u16) -> RequestChannelBuilder {

0 commit comments

Comments
 (0)