From 4b7c046a1614ba2f08a40d07ee784b3285870ca3 Mon Sep 17 00:00:00 2001 From: Guilherme Perinazzo Date: Mon, 22 Mar 2021 10:51:49 -0300 Subject: [PATCH 1/3] Fix underflow on array and binary deserialization Closes #243 --- src/de/mod.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/de/mod.rs b/src/de/mod.rs index 0fe3a9aa..3cdfe182 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -176,6 +176,13 @@ fn deserialize_array(reader: &mut R, utf8_lossy: bool) -> Resu let mut arr = Array::new(); let length = read_i32(reader)?; + if !(MIN_BSON_DOCUMENT_SIZE..=MAX_BSON_SIZE).contains(&length) { + return Err(Error::invalid_length( + length as usize, + &format!("array length must be between {} and {}", MIN_BSON_DOCUMENT_SIZE, MAX_BSON_SIZE).as_str(), + )); + } + ensure_read_exactly( reader, (length as usize) - 4, @@ -224,6 +231,14 @@ pub(crate) fn deserialize_bson_kvp( if let BinarySubtype::BinaryOld = subtype { let data_len = read_i32(reader)?; + if !(0..=(MAX_BSON_SIZE - 4)).contains(&data_len) { + return Err(Error::invalid_length( + data_len as usize, + &format!("0x02 length must be between 0 and {}", MAX_BSON_SIZE - 4).as_str(), + )); + + } + if data_len + 4 != len { return Err(Error::invalid_length( data_len as usize, From e899afce34b6be659b6e8e8787b30db5182a5a35 Mon Sep 17 00:00:00 2001 From: Guilherme Perinazzo Date: Mon, 22 Mar 2021 20:38:14 -0300 Subject: [PATCH 2/3] Add tests for RUST-713 --- src/tests/modules/serializer_deserializer.rs | 22 ++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/tests/modules/serializer_deserializer.rs b/src/tests/modules/serializer_deserializer.rs index cbc87fcd..bc987c85 100644 --- a/src/tests/modules/serializer_deserializer.rs +++ b/src/tests/modules/serializer_deserializer.rs @@ -540,3 +540,25 @@ fn test_serialize_deserialize_document() { let bad_point: Result = from_document(bad_point); assert!(bad_point.is_err()); } + +/// [RUST-713](https://jira.mongodb.org/browse/RUST-713) +#[test] +fn test_deserialize_invalid_array_length() { + let _guard = LOCK.run_concurrently(); + let buffer = b"\n\x00\x00\x00\x04\x00\x00\x00\x00\x00"; + Document::from_reader(&mut std::io::Cursor::new(buffer)) + .expect_err("expected deserialization to fail") ; +} + +/// [RUST-713](https://jira.mongodb.org/browse/RUST-713) +#[test] +fn test_deserialize_invalid_old_binary_length() { + let _guard = LOCK.run_concurrently(); + let buffer = b"\x0F\x00\x00\x00\x05\x00\x00\x00\x00\x00\x02\xFC\xFF\xFF\xFF"; + Document::from_reader(&mut std::io::Cursor::new(buffer)) + .expect_err("expected deserialization to fail") ; + + let buffer = b".\x00\x00\x00\x05\x01\x00\x00\x00\x00\x00\x02\xfc\xff\xff\xff\xff\xff\xff\xff\x00\x00*\x00h\x0e\x10++\x00h\x0e++\x00\x00\t\x00\x00\x00\x00\x00*\x0e\x10++"; + Document::from_reader(&mut std::io::Cursor::new(buffer)) + .expect_err("expected deserialization to fail") ; +} From 14fdf79d6b1d324ece1251f6190417ec8470e8c7 Mon Sep 17 00:00:00 2001 From: Patrick Freed Date: Wed, 24 Mar 2021 12:05:50 -0400 Subject: [PATCH 3/3] fix lint --- src/de/mod.rs | 10 +++++++--- src/tests/modules/serializer_deserializer.rs | 6 +++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/de/mod.rs b/src/de/mod.rs index 3cdfe182..401dc432 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -179,7 +179,11 @@ fn deserialize_array(reader: &mut R, utf8_lossy: bool) -> Resu if !(MIN_BSON_DOCUMENT_SIZE..=MAX_BSON_SIZE).contains(&length) { return Err(Error::invalid_length( length as usize, - &format!("array length must be between {} and {}", MIN_BSON_DOCUMENT_SIZE, MAX_BSON_SIZE).as_str(), + &format!( + "array length must be between {} and {}", + MIN_BSON_DOCUMENT_SIZE, MAX_BSON_SIZE + ) + .as_str(), )); } @@ -234,9 +238,9 @@ pub(crate) fn deserialize_bson_kvp( if !(0..=(MAX_BSON_SIZE - 4)).contains(&data_len) { return Err(Error::invalid_length( data_len as usize, - &format!("0x02 length must be between 0 and {}", MAX_BSON_SIZE - 4).as_str(), + &format!("0x02 length must be between 0 and {}", MAX_BSON_SIZE - 4) + .as_str(), )); - } if data_len + 4 != len { diff --git a/src/tests/modules/serializer_deserializer.rs b/src/tests/modules/serializer_deserializer.rs index bc987c85..33e6f9c8 100644 --- a/src/tests/modules/serializer_deserializer.rs +++ b/src/tests/modules/serializer_deserializer.rs @@ -547,7 +547,7 @@ fn test_deserialize_invalid_array_length() { let _guard = LOCK.run_concurrently(); let buffer = b"\n\x00\x00\x00\x04\x00\x00\x00\x00\x00"; Document::from_reader(&mut std::io::Cursor::new(buffer)) - .expect_err("expected deserialization to fail") ; + .expect_err("expected deserialization to fail"); } /// [RUST-713](https://jira.mongodb.org/browse/RUST-713) @@ -556,9 +556,9 @@ fn test_deserialize_invalid_old_binary_length() { let _guard = LOCK.run_concurrently(); let buffer = b"\x0F\x00\x00\x00\x05\x00\x00\x00\x00\x00\x02\xFC\xFF\xFF\xFF"; Document::from_reader(&mut std::io::Cursor::new(buffer)) - .expect_err("expected deserialization to fail") ; + .expect_err("expected deserialization to fail"); let buffer = b".\x00\x00\x00\x05\x01\x00\x00\x00\x00\x00\x02\xfc\xff\xff\xff\xff\xff\xff\xff\x00\x00*\x00h\x0e\x10++\x00h\x0e++\x00\x00\t\x00\x00\x00\x00\x00*\x0e\x10++"; Document::from_reader(&mut std::io::Cursor::new(buffer)) - .expect_err("expected deserialization to fail") ; + .expect_err("expected deserialization to fail"); }