Skip to content

Fix windows Socket::connect_timeout overflow #112464

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 20, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions library/std/src/net/tcp/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,37 @@ fn connect_error() {
}
}

#[test]
fn connect_timeout_to_unreachable_address() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested, this unit test will cost at 2 minutes and 8 seconds on Linux platform, and cost 20 seconds on Windows.

Copy link
Member

@ChrisDenton ChrisDenton Jun 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we only need one test here. We only need to focus on testing the problematic code path in one way. 2 minutes and 8 secs is a long time for a single unit test so I'd prefer if we just used connect_timeout_error test and removed the other two.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I think 2 minutes and 8 seconds is a long time too.

let now = Instant::now();
match TcpStream::connect_timeout(&format!("1.1.1.1:9999").parse().unwrap(), Duration::MAX) {
Ok(..) => panic!("connected to an unreachable address, this is impossible"),
Err(e) => assert_eq!(e.kind(), ErrorKind::TimedOut),
}

assert!(now.elapsed() > Duration::from_secs(20));
}

#[test]
fn connect_timeout_error() {
let socket_addr = next_test_ip4();
let result = TcpStream::connect_timeout(&socket_addr, Duration::MAX);
assert!(!matches!(result, Err(e) if e.kind() == ErrorKind::TimedOut));

let _listener = TcpListener::bind(&socket_addr).unwrap();
assert!(TcpStream::connect_timeout(&socket_addr, Duration::MAX).is_ok());
}

#[test]
fn connect_timeout_ok_bind() {
let listener = TcpListener::bind("127.0.0.1:0").unwrap(); // :0 picks some free port
let port = listener.local_addr().unwrap().port(); // obtain the port it picked
assert!(
TcpStream::connect_timeout(&format!("127.0.0.1:{port}").parse().unwrap(), Duration::MAX)
.is_ok()
);
}

#[test]
fn listen_localhost() {
let socket_addr = next_test_ip4();
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sys/windows/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ impl Socket {
}

let mut timeout = c::timeval {
tv_sec: timeout.as_secs() as c_long,
tv_sec: cmp::min(timeout.as_secs(), c_long::MAX as u64) as c_long,
tv_usec: (timeout.subsec_nanos() / 1000) as c_long,
};

Expand Down