Add checks for ports (#11214)

# 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:🐚: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
This commit is contained in:
nibon7 2023-12-03 22:07:15 +08:00 committed by GitHub
parent 58d002d469
commit b227eea668
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 1 deletions

View file

@ -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,

View file

@ -47,3 +47,10 @@ fn port_from_system_given() {
// check that we can get an integer port from system.
assert!(actual.out.parse::<u16>().unwrap() > 0)
}
#[test]
fn port_out_of_range() {
let actual = nu!("port 65536 99999");
assert!(actual.err.contains("can't convert usize to u16"));
}