Skip to content

Commit bfde122

Browse files
authored
feat: extend fuzzing, fix one found issue (#294)
* feat: fuzz more protocol messages * fix: avoid `CompactBytes::read` "substract with over/underflow"
1 parent b2c2222 commit bfde122

File tree

2 files changed

+61
-4
lines changed

2 files changed

+61
-4
lines changed

fuzz/fuzz_targets/protocol_reader.rs

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,13 @@ use rskafka::{
1818
api_version::{ApiVersion, ApiVersionRange},
1919
frame::AsyncMessageWrite,
2020
messages::{
21-
ApiVersionsRequest, CreateTopicsRequest, FetchRequest, ListOffsetsRequest,
22-
MetadataRequest, ProduceRequest, ReadVersionedType, RequestBody, WriteVersionedType,
21+
ApiVersionsRequest, CreateTopicsRequest, DeleteRecordsRequest, DeleteTopicsRequest,
22+
FetchRequest, ListOffsetsRequest, MetadataRequest, ProduceRequest, ReadVersionedType,
23+
RequestBody, SaslAuthenticateRequest, SaslHandshakeRequest, WriteVersionedType,
24+
},
25+
primitives::{
26+
Array, Bytes, CompactString, Int16, Int32, NullableString, String_, TaggedFields,
2327
},
24-
primitives::{CompactString, Int16, Int32, NullableString, TaggedFields},
2528
traits::ReadType,
2629
},
2730
};
@@ -61,6 +64,26 @@ fn driver(data: &[u8]) -> Result<(), Error> {
6164
api_key,
6265
api_version,
6366
),
67+
ApiKey::DeleteRecords => send_recv(
68+
DeleteRecordsRequest {
69+
topics: vec![],
70+
timeout_ms: Int32(0),
71+
tagged_fields: None,
72+
},
73+
cursor,
74+
api_key,
75+
api_version,
76+
),
77+
ApiKey::DeleteTopics => send_recv(
78+
DeleteTopicsRequest {
79+
topic_names: Array(None),
80+
timeout_ms: Int32(0),
81+
tagged_fields: None,
82+
},
83+
cursor,
84+
api_key,
85+
api_version,
86+
),
6487
ApiKey::Fetch => send_recv(
6588
FetchRequest {
6689
replica_id: Int32(0),
@@ -104,6 +127,23 @@ fn driver(data: &[u8]) -> Result<(), Error> {
104127
api_key,
105128
api_version,
106129
),
130+
ApiKey::SaslAuthenticate => send_recv(
131+
SaslAuthenticateRequest {
132+
auth_bytes: Bytes(vec![]),
133+
tagged_fields: None,
134+
},
135+
cursor,
136+
api_key,
137+
api_version,
138+
),
139+
ApiKey::SaslHandshake => send_recv(
140+
SaslHandshakeRequest {
141+
mechanism: String_(String::new()),
142+
},
143+
cursor,
144+
api_key,
145+
api_version,
146+
),
107147
_ => Err(format!("Fuzzing not implemented for: {api_key:?}").into()),
108148
}
109149
}

src/protocol/primitives.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,14 +515,17 @@ where
515515
#[derive(Debug, Eq, PartialEq)]
516516
#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
517517
pub struct CompactBytes(pub Vec<u8>);
518+
518519
impl<R> ReadType<R> for CompactBytes
519520
where
520521
R: Read,
521522
{
522523
fn read(reader: &mut R) -> Result<Self, ReadError> {
523524
let len = UnsignedVarint::read(reader)?;
524525
let len = usize::try_from(len.0)?;
525-
let len = len - 1;
526+
let len = len.checked_sub(1).ok_or_else(|| {
527+
ReadError::Malformed(format!("Must be able to substract 1 from len ({len})").into())
528+
})?;
526529
let mut buf = VecBuilder::new(len);
527530
buf = buf.read_exact(reader)?;
528531
Ok(Self(buf.into()))
@@ -1028,6 +1031,20 @@ mod tests {
10281031

10291032
test_roundtrip!(CompactBytes, test_compact_bytes_roundtrip);
10301033

1034+
#[test]
1035+
fn test_compact_read_negative_length() {
1036+
let mut buf = Cursor::new(Vec::<u8>::new());
1037+
UnsignedVarint(0).write(&mut buf).unwrap();
1038+
buf.set_position(0);
1039+
1040+
let err = CompactBytes::read(&mut buf).unwrap_err();
1041+
assert_matches!(err, ReadError::Malformed(_));
1042+
assert_eq!(
1043+
err.to_string(),
1044+
"Malformed data: Must be able to substract 1 from len (0)",
1045+
);
1046+
}
1047+
10311048
test_roundtrip!(NullableBytes, test_nullable_bytes_roundtrip);
10321049

10331050
#[test]

0 commit comments

Comments
 (0)