diff --git a/crates/collab-net/src/invite.rs b/crates/collab-net/src/invite.rs index 617ad518..47ca1850 100644 --- a/crates/collab-net/src/invite.rs +++ b/crates/collab-net/src/invite.rs @@ -220,7 +220,8 @@ fn valid_host(s: &str) -> bool { return true; } let Some((name, port)) = s.rsplit_once(':') else { return false }; - port.parse::().is_ok_and(|p| p != 0) + port.bytes().all(|b| b.is_ascii_digit()) + && port.parse::().is_ok_and(|p| p != 0) && (1..=253).contains(&name.len()) && name.bytes().all(|b| b.is_ascii_alphanumeric() || b == b'-' || b == b'.') && !name.starts_with(['-', '.']) diff --git a/crates/collab-net/src/invite_tests.rs b/crates/collab-net/src/invite_tests.rs index 02017517..d4d13296 100644 --- a/crates/collab-net/src/invite_tests.rs +++ b/crates/collab-net/src/invite_tests.rs @@ -123,3 +123,11 @@ proptest! { prop_assert_eq!(Invite::parse(&i.url()), Ok(i)); } } + +#[test] +fn port_must_be_all_digits() { + assert!(Endpoint::parse("ws://localhost:80/").is_ok()); + for bad in ["ws://localhost:+80/", "ws://localhost:-80/", "ws://localhost:/"] { + assert!(Endpoint::parse(bad).is_err(), "accepted {bad}"); + } +}