Skip to content

Commit

Permalink
be more strict about brackets around ip address
Browse files Browse the repository at this point in the history
  • Loading branch information
glendc committed Jun 11, 2024
1 parent 31f59d3 commit e2c78ef
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 15 deletions.
20 changes: 12 additions & 8 deletions src/net/address/authority.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use super::Host;
use crate::error::{ErrorContext, OpaqueError};
use std::{fmt, net::SocketAddr};
use std::{
fmt,
net::{IpAddr, SocketAddr},
};

/// A [`Host`] with an associated port.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
Expand Down Expand Up @@ -133,7 +136,12 @@ impl TryFrom<&str> for Authority {

let (host, port) = try_to_split_port_from_str(s)?;
let host = Host::try_from(host).context("parse host from authority")?;
Ok(Authority { host, port })
match host {
Host::Address(IpAddr::V6(_)) if port.is_some() && !s.starts_with('[') => Err(
OpaqueError::from_display("missing brackets for IPv6 address with port"),
),
_ => Ok(Authority { host, port }),
}
}
}

Expand Down Expand Up @@ -184,7 +192,6 @@ mod tests {
("[::1]:80", ("::1", Some(80))),
("127.0.0.1", ("127.0.0.1", None)),
("127.0.0.1:80", ("127.0.0.1", Some(80))),
("[127.0.0.1]:80", ("127.0.0.1", Some(80))), // 🤷 technically not correct, but...
(
"2001:db8:3333:4444:5555:6666:7777:8888",
("2001:db8:3333:4444:5555:6666:7777:8888", None),
Expand All @@ -197,10 +204,6 @@ mod tests {
"[2001:db8:3333:4444:5555:6666:7777:8888]:80",
("2001:db8:3333:4444:5555:6666:7777:8888", Some(80)),
),
(
"2001:db8:3333:4444:5555:6666:7777:8888:80", // 🤷 technically not correct, but...
("2001:db8:3333:4444:5555:6666:7777:8888", Some(80)),
),
] {
let msg = format!("parsing '{}'", s);

Expand Down Expand Up @@ -241,6 +244,8 @@ mod tests {
"example.com:-1",
"example.com:999999",
"example:com",
"[127.0.0.1]:80",
"2001:db8:3333:4444:5555:6666:7777:8888:80",
] {
let msg = format!("parsing '{}'", s);
assert!(s.parse::<Authority>().is_err(), "{}", msg);
Expand All @@ -266,7 +271,6 @@ mod tests {
("[::1]:80", "[::1]:80"),
("127.0.0.1", "127.0.0.1"),
("127.0.0.1:80", "127.0.0.1:80"),
("[127.0.0.1]:80", "127.0.0.1:80"), // 🤷 technically not correct, but...
] {
let msg = format!("parsing '{}'", s);
let authority: Authority = s.parse().expect(&msg);
Expand Down
17 changes: 10 additions & 7 deletions src/net/address/host.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use super::{Authority, Domain};
use crate::error::{ErrorContext, OpaqueError};
use std::{fmt, net::IpAddr};
use std::{
fmt,
net::{IpAddr, Ipv6Addr},
};

/// Either a [`Domain`] or an [`IpAddr`].
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
Expand Down Expand Up @@ -133,14 +136,14 @@ impl TryFrom<&[u8]> for Host {
}

fn try_to_parse_str_to_ip(value: &str) -> Option<IpAddr> {
let value_str = if value.starts_with('[') || value.ends_with(']') {
value
if value.starts_with('[') || value.ends_with(']') {
let value = value
.strip_prefix('[')
.and_then(|value| value.strip_suffix(']'))?
.and_then(|value| value.strip_suffix(']'))?;
Some(IpAddr::V6(value.parse::<Ipv6Addr>().ok()?))
} else {
value
};
value_str.parse::<IpAddr>().ok()
value.parse::<IpAddr>().ok()
}
}

fn try_to_parse_bytes_to_ip(value: &[u8]) -> Option<IpAddr> {
Expand Down

0 comments on commit e2c78ef

Please sign in to comment.