diff options
author | cypherpunks <cypherpunks@torproject.org> | 2018-08-09 21:26:10 +0000 |
---|---|---|
committer | cypherpunks <cypherpunks@torproject.org> | 2018-09-14 15:08:55 +0000 |
commit | c613d5513491861431c2852cf4072ae256ba2c67 (patch) | |
tree | 97e1d8e1ef58f56cf129ec10f00ddbf7119a5979 | |
parent | 578f7326eda7307c420286c01b57f71925901533 (diff) | |
download | tor-c613d5513491861431c2852cf4072ae256ba2c67.tar.gz tor-c613d5513491861431c2852cf4072ae256ba2c67.zip |
rust/protover: use .and_not_in() instead of .retain() in all_supported()
.retain() would allocating a Vec of billions of integers and check them
one at a time to separate the supported versions from the unsupported.
This leads to a memory DoS.
Closes ticket 27206. Bugfix on e6625113c98c281b0a649598d7daa347c28915e9.
-rw-r--r-- | changes/bug27206 | 4 | ||||
-rw-r--r-- | src/rust/protover/protover.rs | 4 | ||||
-rw-r--r-- | src/rust/protover/tests/protover.rs | 8 |
3 files changed, 9 insertions, 7 deletions
diff --git a/changes/bug27206 b/changes/bug27206 new file mode 100644 index 0000000000..c0fbbed702 --- /dev/null +++ b/changes/bug27206 @@ -0,0 +1,4 @@ + o Minor bugfixes (rust): + - protover_all_supported() would attempt to allocate up to 16GB on some + inputs, leading to a potential memory DoS. Fixes bug 27206; bugfix on + 0.3.3.5-rc. diff --git a/src/rust/protover/protover.rs b/src/rust/protover/protover.rs index b3563b0637..c11c7c1803 100644 --- a/src/rust/protover/protover.rs +++ b/src/rust/protover/protover.rs @@ -365,7 +365,6 @@ impl UnvalidatedProtoEntry { let maybe_supported_versions: Option<&ProtoSet> = supported.get(&supported_protocol); let supported_versions: &ProtoSet; - let mut unsupported_versions: ProtoSet; // If the protocol wasn't in the map, then we don't know about it // and don't support any of its versions. Add its versions to the @@ -378,8 +377,7 @@ impl UnvalidatedProtoEntry { } else { supported_versions = maybe_supported_versions.unwrap(); } - unsupported_versions = versions.clone(); - unsupported_versions.retain(|x| !supported_versions.contains(x)); + let unsupported_versions = versions.and_not_in(supported_versions); if !unsupported_versions.is_empty() { unsupported.insert(protocol.clone(), unsupported_versions); diff --git a/src/rust/protover/tests/protover.rs b/src/rust/protover/tests/protover.rs index 59a4b5a8a0..9258d869d7 100644 --- a/src/rust/protover/tests/protover.rs +++ b/src/rust/protover/tests/protover.rs @@ -354,18 +354,18 @@ fn protover_all_supported_should_exclude_some_versions_and_entire_protocols() { #[test] fn protover_all_supported_should_not_dos_anyones_computer() { - let proto: UnvalidatedProtoEntry = "Sleen=1-2147483648".parse().unwrap(); + let proto: UnvalidatedProtoEntry = "Link=1-2147483648".parse().unwrap(); let result: String = proto.all_supported().unwrap().to_string(); - assert_eq!(result, "Sleen=1-2147483648".to_string()); + assert_eq!(result, "Link=6-2147483648".to_string()); } #[test] fn protover_all_supported_should_not_dos_anyones_computer_max_versions() { - let proto: UnvalidatedProtoEntry = "Sleen=1-4294967294".parse().unwrap(); + let proto: UnvalidatedProtoEntry = "Link=1-4294967294".parse().unwrap(); let result: String = proto.all_supported().unwrap().to_string(); - assert_eq!(result, "Sleen=1-4294967294".to_string()); + assert_eq!(result, "Link=6-4294967294".to_string()); } #[test] |