Skip to content

Commit deff138

Browse files
authored
recvfrom: don't convert address if addrsize is 0 (#1153)
1 parent b6e40a3 commit deff138

File tree

2 files changed

+51
-3
lines changed

2 files changed

+51
-3
lines changed

libc/sock/recvfrom.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ ssize_t recvfrom(int fd, void *buf, size_t size, int flags,
7070
if (__isfdkind(fd, kFdSocket)) {
7171
rc = sys_recvfrom_nt(fd, (struct iovec[]){{buf, size}}, 1, flags, &addr,
7272
&addrsize);
73+
if (rc != -1 && addrsize == sizeof(addr)) {
74+
addrsize = 0;
75+
}
7376
} else if (__isfdkind(fd, kFdFile) && !opt_out_srcaddr) { /* socketpair */
7477
if (!flags) {
7578
rc = sys_read_nt(fd, (struct iovec[]){{buf, size}}, 1, -1);
@@ -84,10 +87,14 @@ ssize_t recvfrom(int fd, void *buf, size_t size, int flags,
8487
}
8588

8689
if (rc != -1) {
87-
if (IsBsd()) {
88-
__convert_bsd_to_sockaddr(&addr);
90+
if (addrsize) {
91+
if (IsBsd()) {
92+
__convert_bsd_to_sockaddr(&addr);
93+
}
94+
__write_sockaddr(&addr, opt_out_srcaddr, opt_inout_srcaddrsize);
95+
} else {
96+
*opt_inout_srcaddrsize = 0;
8997
}
90-
__write_sockaddr(&addr, opt_out_srcaddr, opt_inout_srcaddrsize);
9198
}
9299

93100
END_CANCELATION_POINT;

test/libc/sock/recvfrom_test.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,44 @@ TEST(recvfrom, test) {
9393
EXPECT_SYS(0, 0, close(client1));
9494
WAIT(exit, 0);
9595
}
96+
97+
// server listens for connections, accepts a connection, and sends data
98+
// client connects to server recieves with recvfrom and verifies addrsize
99+
// is 0 as the sender info isn't available on connection sockets.
100+
TEST(recvfrom, tcp) {
101+
uint32_t addrsize = sizeof(struct sockaddr_in);
102+
struct sockaddr_in server = {
103+
.sin_family = AF_INET,
104+
.sin_addr.s_addr = htonl(0x7f000001),
105+
};
106+
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
107+
ASSERT_SYS(0, 0, bind(3, (struct sockaddr *)&server, sizeof(server)));
108+
ASSERT_SYS(0, 0, getsockname(3, (struct sockaddr *)&server, &addrsize));
109+
ASSERT_SYS(0, 0, listen(3, 5));
110+
111+
////////////////////////////////////////////////////////////////////////////////
112+
SPAWN(fork);
113+
struct sockaddr_in data, addr;
114+
uint32_t addrsize = sizeof(struct sockaddr_in);
115+
EXPECT_SYS(0, 0, close(3));
116+
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
117+
ASSERT_SYS(0, 0, connect(3, (struct sockaddr *)&server, sizeof(server)));
118+
ASSERT_SYS(
119+
0, sizeof(data),
120+
recvfrom(3, &data, sizeof(data), 0, (struct sockaddr *)&addr, &addrsize));
121+
ASSERT_EQ(0, addrsize);
122+
EXPECT_SYS(0, 0, close(3));
123+
124+
////////////////////////////////////////////////////////////////////////////////
125+
PARENT();
126+
int client;
127+
struct sockaddr client_sockaddr;
128+
uint32_t sockaddr_size = sizeof(client_sockaddr);
129+
ASSERT_NE(-1, (client = accept(3, &client_sockaddr, &sockaddr_size)));
130+
ASSERT_SYS(0, sizeof(client_sockaddr),
131+
sendto(client, &client_sockaddr, sizeof(client_sockaddr), 0,
132+
(struct sockaddr *)&server, sizeof(server)));
133+
EXPECT_SYS(0, 0, close(client));
134+
WAIT(exit, 0);
135+
EXPECT_SYS(0, 0, close(3));
136+
}

0 commit comments

Comments
 (0)