Merge remote-tracking branch 'onionk/rust-protokeyword1-035'

This commit is contained in:
Nick Mathewson 2018-09-14 09:25:31 -04:00
commit 84e3ada71b
3 changed files with 41 additions and 1 deletions

4
changes/bug27687 Normal file
View File

@ -0,0 +1,4 @@
o Minor bugfixes (rust):
- protover parsed and accepted unknown protocol names containing invalid
characters outside the range [A-Za-z0-9-]. Fixes bug 27687; bugfix on
0.3.3.1-alpha.

View File

@ -18,6 +18,7 @@ pub enum ProtoverError {
ExceedsExpansionLimit,
UnknownProtocol,
ExceedsNameLimit,
InvalidProtocol,
}
/// Descriptive error messages for `ProtoverError` variants.
@ -48,6 +49,9 @@ impl Display for ProtoverError {
ProtoverError::ExceedsNameLimit => {
write!(f, "An unrecognised protocol name was too long.")
}
ProtoverError::InvalidProtocol => {
write!(f, "A protocol name includes invalid characters.")
}
}
}
}

View File

@ -89,11 +89,17 @@ impl fmt::Display for UnknownProtocol {
}
}
fn is_valid_proto(s: &str) -> bool {
s.chars().all(|c| c.is_ascii_alphanumeric() || c == '-')
}
impl FromStr for UnknownProtocol {
type Err = ProtoverError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s.len() <= MAX_PROTOCOL_NAME_LENGTH {
if !is_valid_proto(s) {
Err(ProtoverError::InvalidProtocol)
} else if s.len() <= MAX_PROTOCOL_NAME_LENGTH {
Ok(UnknownProtocol(s.to_string()))
} else {
Err(ProtoverError::ExceedsNameLimit)
@ -105,6 +111,9 @@ impl UnknownProtocol {
/// Create an `UnknownProtocol`, ignoring whether or not it
/// exceeds MAX_PROTOCOL_NAME_LENGTH.
fn from_str_any_len(s: &str) -> Result<Self, ProtoverError> {
if !is_valid_proto(s) {
return Err(ProtoverError::InvalidProtocol);
}
Ok(UnknownProtocol(s.to_string()))
}
}
@ -772,6 +781,29 @@ mod test {
use super::*;
macro_rules! parse_proto {
($e:expr) => {{
let proto: Result<UnknownProtocol, _> = $e.parse();
let proto2 = UnknownProtocol::from_str_any_len($e);
assert_eq!(proto, proto2);
proto
}};
}
#[test]
fn test_protocol_from_str() {
assert!(parse_proto!("Cons").is_ok());
assert!(parse_proto!("123").is_ok());
assert!(parse_proto!("1-2-3").is_ok());
let err = Err(ProtoverError::InvalidProtocol);
assert_eq!(err, parse_proto!("a_b_c"));
assert_eq!(err, parse_proto!("a b"));
assert_eq!(err, parse_proto!("a,"));
assert_eq!(err, parse_proto!("b."));
assert_eq!(err, parse_proto!(""));
}
macro_rules! assert_protoentry_is_parseable {
($e:expr) => {
let protoentry: Result<ProtoEntry, ProtoverError> = $e.parse();