From b227eea6682ede22bccec71c552156775440d424 Mon Sep 17 00:00:00 2001 From: nibon7 Date: Sun, 3 Dec 2023 22:07:15 +0800 Subject: [PATCH] Add checks for ports (#11214) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description This PR adds checks for ports. This fixes unexpected output similar to the one in the comment https://github.com/nushell/nushell/pull/11210#issuecomment-1837152357. * before ```console /data/source/nushell> port 65536 99999 41233 ``` * after ```console /data/source/nushell> port 65536 99999 Error: nu::shell::cant_convert × Can't convert to u16. ╭─[entry #1:1:1] 1 │ port 65536 99999 · ──┬── · ╰── can't convert usize to u16 ╰──── help: out of range integral type conversion attempted (min: 0, max: 65535) ``` # User-Facing Changes N/A # Tests + Formatting * [x] add `port_out_of_range` test # After Submitting N/A --- crates/nu-command/src/network/port.rs | 26 ++++++++++++++++++- .../nu-command/tests/commands/network/port.rs | 7 +++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/crates/nu-command/src/network/port.rs b/crates/nu-command/src/network/port.rs index 5d0a53a4a4..91f087d00e 100644 --- a/crates/nu-command/src/network/port.rs +++ b/crates/nu-command/src/network/port.rs @@ -79,11 +79,35 @@ fn get_free_port( None => (1024, None), }; + let start_port = match u16::try_from(start_port) { + Ok(p) => p, + Err(e) => { + return Err(ShellError::CantConvert { + to_type: "u16".into(), + from_type: "usize".into(), + span: start_span.unwrap_or(call.head), + help: Some(format!("{e} (min: {}, max: {})", u16::MIN, u16::MAX)), + }); + } + }; + let (end_port, end_span) = match end_port { Some(p) => (p.item, Some(p.span)), None => (65535, None), }; + let end_port = match u16::try_from(end_port) { + Ok(p) => p, + Err(e) => { + return Err(ShellError::CantConvert { + to_type: "u16".into(), + from_type: "usize".into(), + span: end_span.unwrap_or(call.head), + help: Some(format!("{e} (min: {}, max: {})", u16::MIN, u16::MAX)), + }); + } + }; + let range_span = match (start_span, end_span) { (Some(start), Some(end)) => Span::new(start.start, end.end), (Some(start), None) => start, @@ -102,7 +126,7 @@ fn get_free_port( // try given port one by one. match (start_port..=end_port) - .map(|port| SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, port as u16))) + .map(|port| SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, port))) .find_map(|addr| TcpListener::bind(addr).ok()) { Some(listener) => listener, diff --git a/crates/nu-command/tests/commands/network/port.rs b/crates/nu-command/tests/commands/network/port.rs index d5921face4..1af1b358ff 100644 --- a/crates/nu-command/tests/commands/network/port.rs +++ b/crates/nu-command/tests/commands/network/port.rs @@ -47,3 +47,10 @@ fn port_from_system_given() { // check that we can get an integer port from system. assert!(actual.out.parse::().unwrap() > 0) } + +#[test] +fn port_out_of_range() { + let actual = nu!("port 65536 99999"); + + assert!(actual.err.contains("can't convert usize to u16")); +}