mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
recvfrom: don't convert address if addrsize is 0 (#1153)
This commit is contained in:
parent
b6e40a3a58
commit
deff138e7e
2 changed files with 51 additions and 3 deletions
|
@ -70,6 +70,9 @@ ssize_t recvfrom(int fd, void *buf, size_t size, int flags,
|
||||||
if (__isfdkind(fd, kFdSocket)) {
|
if (__isfdkind(fd, kFdSocket)) {
|
||||||
rc = sys_recvfrom_nt(fd, (struct iovec[]){{buf, size}}, 1, flags, &addr,
|
rc = sys_recvfrom_nt(fd, (struct iovec[]){{buf, size}}, 1, flags, &addr,
|
||||||
&addrsize);
|
&addrsize);
|
||||||
|
if (rc != -1 && addrsize == sizeof(addr)) {
|
||||||
|
addrsize = 0;
|
||||||
|
}
|
||||||
} else if (__isfdkind(fd, kFdFile) && !opt_out_srcaddr) { /* socketpair */
|
} else if (__isfdkind(fd, kFdFile) && !opt_out_srcaddr) { /* socketpair */
|
||||||
if (!flags) {
|
if (!flags) {
|
||||||
rc = sys_read_nt(fd, (struct iovec[]){{buf, size}}, 1, -1);
|
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc != -1) {
|
if (rc != -1) {
|
||||||
if (IsBsd()) {
|
if (addrsize) {
|
||||||
__convert_bsd_to_sockaddr(&addr);
|
if (IsBsd()) {
|
||||||
|
__convert_bsd_to_sockaddr(&addr);
|
||||||
|
}
|
||||||
|
__write_sockaddr(&addr, opt_out_srcaddr, opt_inout_srcaddrsize);
|
||||||
|
} else {
|
||||||
|
*opt_inout_srcaddrsize = 0;
|
||||||
}
|
}
|
||||||
__write_sockaddr(&addr, opt_out_srcaddr, opt_inout_srcaddrsize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
END_CANCELATION_POINT;
|
END_CANCELATION_POINT;
|
||||||
|
|
|
@ -93,3 +93,44 @@ TEST(recvfrom, test) {
|
||||||
EXPECT_SYS(0, 0, close(client1));
|
EXPECT_SYS(0, 0, close(client1));
|
||||||
WAIT(exit, 0);
|
WAIT(exit, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// server listens for connections, accepts a connection, and sends data
|
||||||
|
// client connects to server recieves with recvfrom and verifies addrsize
|
||||||
|
// is 0 as the sender info isn't available on connection sockets.
|
||||||
|
TEST(recvfrom, tcp) {
|
||||||
|
uint32_t addrsize = sizeof(struct sockaddr_in);
|
||||||
|
struct sockaddr_in server = {
|
||||||
|
.sin_family = AF_INET,
|
||||||
|
.sin_addr.s_addr = htonl(0x7f000001),
|
||||||
|
};
|
||||||
|
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||||
|
ASSERT_SYS(0, 0, bind(3, (struct sockaddr *)&server, sizeof(server)));
|
||||||
|
ASSERT_SYS(0, 0, getsockname(3, (struct sockaddr *)&server, &addrsize));
|
||||||
|
ASSERT_SYS(0, 0, listen(3, 5));
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
SPAWN(fork);
|
||||||
|
struct sockaddr_in data, addr;
|
||||||
|
uint32_t addrsize = sizeof(struct sockaddr_in);
|
||||||
|
EXPECT_SYS(0, 0, close(3));
|
||||||
|
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||||
|
ASSERT_SYS(0, 0, connect(3, (struct sockaddr *)&server, sizeof(server)));
|
||||||
|
ASSERT_SYS(
|
||||||
|
0, sizeof(data),
|
||||||
|
recvfrom(3, &data, sizeof(data), 0, (struct sockaddr *)&addr, &addrsize));
|
||||||
|
ASSERT_EQ(0, addrsize);
|
||||||
|
EXPECT_SYS(0, 0, close(3));
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
PARENT();
|
||||||
|
int client;
|
||||||
|
struct sockaddr client_sockaddr;
|
||||||
|
uint32_t sockaddr_size = sizeof(client_sockaddr);
|
||||||
|
ASSERT_NE(-1, (client = accept(3, &client_sockaddr, &sockaddr_size)));
|
||||||
|
ASSERT_SYS(0, sizeof(client_sockaddr),
|
||||||
|
sendto(client, &client_sockaddr, sizeof(client_sockaddr), 0,
|
||||||
|
(struct sockaddr *)&server, sizeof(server)));
|
||||||
|
EXPECT_SYS(0, 0, close(client));
|
||||||
|
WAIT(exit, 0);
|
||||||
|
EXPECT_SYS(0, 0, close(3));
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue