Skip to content

Commit 822186d

Browse files
Merge pull request #141 from influxdata/crepererum/fix_snappy_oom
fix: fix potential OOM involving snappy data, found by fuzzer
2 parents 59070f6 + 5f597bd commit 822186d

File tree

1 file changed

+27
-1
lines changed

1 file changed

+27
-1
lines changed

src/protocol/record.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,8 @@ where
630630
// There are "normal" compression libs, and there is Java
631631
// See https://github.com/edenhill/librdkafka/blob/2b76b65212e5efda213961d5f84e565038036270/src/rdkafka_msgset_reader.c#L307-L318
632632
let output = if input.starts_with(JAVA_MAGIC) {
633-
let mut cursor = Cursor::new(&input[JAVA_MAGIC.len()..]);
633+
let cursor_content = &input[JAVA_MAGIC.len()..];
634+
let mut cursor = Cursor::new(cursor_content);
634635

635636
let mut buf_version = [0u8; 4];
636637
cursor.read_exact(&mut buf_version)?;
@@ -653,6 +654,11 @@ where
653654
let mut buf_chunk_length = [0u8; 4];
654655
cursor.read_exact(&mut buf_chunk_length)?;
655656
let chunk_length = u32::from_be_bytes(buf_chunk_length) as usize;
657+
let bytes_left = cursor_content.len() - (cursor.position() as usize);
658+
if chunk_length > bytes_left {
659+
// do NOT try to allocate massive buffer for `chunk_data` but instead fail early
660+
return Err(ReadError::Malformed(format!("Java-specific Snappy-compressed data has illegal chunk length, got {chunk_length} bytes but only {bytes_left} bytes are left.").into()));
661+
}
656662

657663
let mut chunk_data = vec![0u8; chunk_length];
658664
cursor.read_exact(&mut chunk_data)?;
@@ -1312,6 +1318,26 @@ mod tests {
13121318
assert_eq!(actual2, expected);
13131319
}
13141320

1321+
#[test]
1322+
fn test_decode_java_specific_oom() {
1323+
// Found by the fuzzer, this should return an error instead of OOM.
1324+
let data = [
1325+
0x0a, 0x0a, 0x83, 0x00, 0xd4, 0x00, 0x00, 0x22, 0x00, 0x4b, 0x08, 0xd2, 0x22, 0xfb,
1326+
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9b, 0x00, 0x9b, 0x0a, 0x40,
1327+
0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x40, 0x30, 0x00, 0x57, 0x00, 0xd3, 0x82, 0x53,
1328+
0x4e, 0x41, 0x50, 0x50, 0x59, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
1329+
0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0xfc, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09,
1330+
0x09, 0x50, 0x50, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1331+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x30, 0x00, 0x57, 0x00, 0x00, 0x80,
1332+
0x00, 0x00, 0x00, 0x00, 0xb0, 0x9b, 0x00,
1333+
]
1334+
.to_vec();
1335+
1336+
let err = RecordBatchBody::read(&mut Cursor::new(data)).unwrap_err();
1337+
assert_matches!(err, ReadError::Malformed(_));
1338+
assert_eq!(err.to_string(), "Malformed data: Java-specific Snappy-compressed data has illegal chunk length, got 4227860745 bytes but only 38 bytes are left.");
1339+
}
1340+
13151341
#[test]
13161342
fn test_carefully_decompress_snappy_empty_input() {
13171343
let err = carefully_decompress_snappy(&[], 1).unwrap_err();

0 commit comments

Comments
 (0)