Skip to content

Commit d5ba143

Browse files
authored
[lldb] Correct an issue when using Socket to listen on localhost:0 on ipv4 and ipv6. (#118565)
On systems supporting ting ipv4 and ipv6 the second socket to initialize will not update the listening address correctly after the call to `bind`. This results in the second address listed in `Socket::GetListeningConnectionURI` to have port `:0`, which is incorrect. To fix this, correct which address is used to detect the port and update the unit tests to cover this use case. Additionally, I updated the SocketTest's to only parameterize tests that can work on ipv4 or ipv6. This means tests like `SocketTest::DecodeHostAndPort` are only run once, instead of twice since they do not change behavior based on parameters. I also included a new unit test to cover listening on `localhost:0`, validating both sockets correctly list the updated port.
1 parent 0a2116f commit d5ba143

File tree

2 files changed

+35
-16
lines changed

2 files changed

+35
-16
lines changed

lldb/source/Host/common/TCPSocket.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -216,11 +216,11 @@ Status TCPSocket::Listen(llvm::StringRef name, int backlog) {
216216
}
217217

218218
if (host_port->port == 0) {
219-
socklen_t sa_len = address.GetLength();
220-
if (getsockname(fd, &address.sockaddr(), &sa_len) == 0)
221-
host_port->port = address.GetPort();
219+
socklen_t sa_len = listen_address.GetLength();
220+
if (getsockname(fd, &listen_address.sockaddr(), &sa_len) == 0)
221+
host_port->port = listen_address.GetPort();
222222
}
223-
m_listen_sockets[fd] = address;
223+
m_listen_sockets[fd] = listen_address;
224224
}
225225

226226
if (m_listen_sockets.empty()) {

lldb/unittests/Host/SocketTest.cpp

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class SocketTest : public testing::TestWithParam<SocketTestParams> {
3535
}
3636
};
3737

38-
TEST_P(SocketTest, DecodeHostAndPort) {
38+
TEST_F(SocketTest, DecodeHostAndPort) {
3939
EXPECT_THAT_EXPECTED(Socket::DecodeHostAndPort("localhost:1138"),
4040
llvm::HasValue(Socket::HostAndPort{"localhost", 1138}));
4141

@@ -63,19 +63,19 @@ TEST_P(SocketTest, DecodeHostAndPort) {
6363
EXPECT_THAT_EXPECTED(Socket::DecodeHostAndPort("*:65535"),
6464
llvm::HasValue(Socket::HostAndPort{"*", 65535}));
6565

66-
EXPECT_THAT_EXPECTED(
67-
Socket::DecodeHostAndPort("[::1]:12345"),
68-
llvm::HasValue(Socket::HostAndPort{"::1", 12345}));
66+
EXPECT_THAT_EXPECTED(Socket::DecodeHostAndPort("[::1]:12345"),
67+
llvm::HasValue(Socket::HostAndPort{"::1", 12345}));
6968

7069
EXPECT_THAT_EXPECTED(
7170
Socket::DecodeHostAndPort("[abcd:12fg:AF58::1]:12345"),
7271
llvm::HasValue(Socket::HostAndPort{"abcd:12fg:AF58::1", 12345}));
7372
}
7473

7574
#if LLDB_ENABLE_POSIX
76-
TEST_P(SocketTest, DomainListenConnectAccept) {
75+
TEST_F(SocketTest, DomainListenConnectAccept) {
7776
llvm::SmallString<64> Path;
78-
std::error_code EC = llvm::sys::fs::createUniqueDirectory("DomainListenConnectAccept", Path);
77+
std::error_code EC =
78+
llvm::sys::fs::createUniqueDirectory("DomainListenConnectAccept", Path);
7979
ASSERT_FALSE(EC);
8080
llvm::sys::path::append(Path, "test");
8181

@@ -88,7 +88,7 @@ TEST_P(SocketTest, DomainListenConnectAccept) {
8888
CreateDomainConnectedSockets(Path, &socket_a_up, &socket_b_up);
8989
}
9090

91-
TEST_P(SocketTest, DomainListenGetListeningConnectionURI) {
91+
TEST_F(SocketTest, DomainListenGetListeningConnectionURI) {
9292
llvm::SmallString<64> Path;
9393
std::error_code EC =
9494
llvm::sys::fs::createUniqueDirectory("DomainListenConnectAccept", Path);
@@ -110,7 +110,7 @@ TEST_P(SocketTest, DomainListenGetListeningConnectionURI) {
110110
testing::ElementsAre(llvm::formatv("unix-connect://{0}", Path).str()));
111111
}
112112

113-
TEST_P(SocketTest, DomainMainLoopAccept) {
113+
TEST_F(SocketTest, DomainMainLoopAccept) {
114114
llvm::SmallString<64> Path;
115115
std::error_code EC =
116116
llvm::sys::fs::createUniqueDirectory("DomainListenConnectAccept", Path);
@@ -270,6 +270,25 @@ TEST_P(SocketTest, TCPListen0GetListeningConnectionURI) {
270270
.str()));
271271
}
272272

273+
TEST_F(SocketTest, TCPListen0MultiListenerGetListeningConnectionURI) {
274+
if (!HostSupportsIPv6() || !HostSupportsIPv4())
275+
return;
276+
277+
llvm::Expected<std::unique_ptr<TCPSocket>> sock =
278+
Socket::TcpListen("localhost:0", 5);
279+
ASSERT_THAT_EXPECTED(sock, llvm::Succeeded());
280+
ASSERT_TRUE(sock.get()->IsValid());
281+
282+
EXPECT_THAT(sock.get()->GetListeningConnectionURI(),
283+
testing::UnorderedElementsAre(
284+
llvm::formatv("connection://[::1]:{0}",
285+
sock->get()->GetLocalPortNumber())
286+
.str(),
287+
llvm::formatv("connection://[127.0.0.1]:{0}",
288+
sock->get()->GetLocalPortNumber())
289+
.str()));
290+
}
291+
273292
TEST_P(SocketTest, TCPGetConnectURI) {
274293
std::unique_ptr<TCPSocket> socket_a_up;
275294
std::unique_ptr<TCPSocket> socket_b_up;
@@ -297,10 +316,10 @@ TEST_P(SocketTest, UDPGetConnectURI) {
297316
}
298317

299318
#if LLDB_ENABLE_POSIX
300-
TEST_P(SocketTest, DomainGetConnectURI) {
319+
TEST_F(SocketTest, DomainGetConnectURI) {
301320
llvm::SmallString<64> domain_path;
302-
std::error_code EC =
303-
llvm::sys::fs::createUniqueDirectory("DomainListenConnectAccept", domain_path);
321+
std::error_code EC = llvm::sys::fs::createUniqueDirectory(
322+
"DomainListenConnectAccept", domain_path);
304323
ASSERT_FALSE(EC);
305324
llvm::sys::path::append(domain_path, "test");
306325

@@ -325,7 +344,7 @@ INSTANTIATE_TEST_SUITE_P(
325344
testing::Values(SocketTestParams{/*is_ipv6=*/false,
326345
/*localhost_ip=*/"127.0.0.1"},
327346
SocketTestParams{/*is_ipv6=*/true, /*localhost_ip=*/"::1"}),
328-
// Prints "SocketTests/SocketTest.DecodeHostAndPort/ipv4" etc. in test logs.
347+
// Prints "SocketTests/SocketTest.TCPGetAddress/ipv4" etc. in test logs.
329348
[](const testing::TestParamInfo<SocketTestParams> &info) {
330349
return info.param.is_ipv6 ? "ipv6" : "ipv4";
331350
});

0 commit comments

Comments
 (0)