From a4842101ca4a3e082cc65fe381ec1972b96770aa Mon Sep 17 00:00:00 2001 From: Michael Rodler Date: Thu, 8 Jun 2023 19:27:51 +0200 Subject: [PATCH 1/2] When parsing Uri authority, check that the square brackets are in the correct order. This avoids panic when attempting to parse odd strings like `]o[`. Signed-off-by: Michael Rodler Reviewed-by: Daniele Ahmed --- src/uri/authority.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/uri/authority.rs b/src/uri/authority.rs index 7a43bc10..0f701e5f 100644 --- a/src/uri/authority.rs +++ b/src/uri/authority.rs @@ -97,7 +97,7 @@ impl Authority { start_bracket = true; } b']' => { - if end_bracket { + if (!start_bracket) || end_bracket { return Err(ErrorKind::InvalidAuthority.into()); } end_bracket = true; @@ -658,8 +658,7 @@ mod tests { let err = Authority::try_from([0xc0u8].as_ref()).unwrap_err(); assert_eq!(err.0, ErrorKind::InvalidUriChar); - let err = Authority::from_shared(Bytes::from_static([0xc0u8].as_ref())) - .unwrap_err(); + let err = Authority::from_shared(Bytes::from_static([0xc0u8].as_ref())).unwrap_err(); assert_eq!(err.0, ErrorKind::InvalidUriChar); } @@ -667,5 +666,9 @@ mod tests { fn rejects_invalid_use_of_brackets() { let err = Authority::parse_non_empty(b"[]@[").unwrap_err(); assert_eq!(err.0, ErrorKind::InvalidAuthority); + + // reject tie-fighter + let err = Authority::parse_non_empty(b"]o[").unwrap_err(); + assert_eq!(err.0, ErrorKind::InvalidAuthority); } } From aa3c7e9a813c9a0670125598820895cd0fab184c Mon Sep 17 00:00:00 2001 From: Michael Rodler Date: Fri, 9 Jun 2023 15:00:02 +0200 Subject: [PATCH 2/2] early reject URI authority if too many ":" chars Signed-off-by: Michael Rodler --- src/uri/authority.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/uri/authority.rs b/src/uri/authority.rs index 0f701e5f..f41ddd19 100644 --- a/src/uri/authority.rs +++ b/src/uri/authority.rs @@ -69,12 +69,13 @@ impl Authority { // Postcondition: for all Ok() returns, s[..ret.unwrap()] is valid UTF-8 where // ret is the return value. pub(super) fn parse(s: &[u8]) -> Result { - let mut colon_cnt = 0; + let mut colon_cnt = 0u32; let mut start_bracket = false; let mut end_bracket = false; let mut has_percent = false; let mut end = s.len(); let mut at_sign_pos = None; + const MAX_COLONS: u32 = 8; // e.g., [FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80 // Among other things, this loop checks that every byte in s up to the // first '/', '?', or '#' is a valid URI character (or in some contexts, @@ -87,6 +88,9 @@ impl Authority { break; } b':' => { + if colon_cnt >= MAX_COLONS { + return Err(ErrorKind::InvalidAuthority.into()); + } colon_cnt += 1; } b'[' => { @@ -644,6 +648,12 @@ mod tests { assert_eq!(result, authority_str); } + #[test] + fn reject_obviously_invalid_ipv6_address() { + let err = Authority::parse_non_empty(b"[0:1:2:3:4:5:6:7:8:9:10:11:12:13:14]").unwrap_err(); + assert_eq!(err.0, ErrorKind::InvalidAuthority); + } + #[test] fn rejects_percent_outside_ipv6_address() { let err = Authority::parse_non_empty(b"1234%20[fe80::1:2:3:4]").unwrap_err();