From deff138e7eb4b0f89ea390b26715a3e543e9bd12 Mon Sep 17 00:00:00 2001 From: Gavin Hayes Date: Fri, 3 May 2024 11:03:57 -0400 Subject: [PATCH] recvfrom: don't convert address if addrsize is 0 (#1153) --- libc/sock/recvfrom.c | 13 ++++++++--- test/libc/sock/recvfrom_test.c | 41 ++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/libc/sock/recvfrom.c b/libc/sock/recvfrom.c index 98cd7317e..d3e326f1b 100644 --- a/libc/sock/recvfrom.c +++ b/libc/sock/recvfrom.c @@ -70,6 +70,9 @@ ssize_t recvfrom(int fd, void *buf, size_t size, int flags, if (__isfdkind(fd, kFdSocket)) { rc = sys_recvfrom_nt(fd, (struct iovec[]){{buf, size}}, 1, flags, &addr, &addrsize); + if (rc != -1 && addrsize == sizeof(addr)) { + addrsize = 0; + } } else if (__isfdkind(fd, kFdFile) && !opt_out_srcaddr) { /* socketpair */ if (!flags) { 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 (IsBsd()) { - __convert_bsd_to_sockaddr(&addr); + if (addrsize) { + 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; diff --git a/test/libc/sock/recvfrom_test.c b/test/libc/sock/recvfrom_test.c index 8126a8f4e..4ef3c7a11 100644 --- a/test/libc/sock/recvfrom_test.c +++ b/test/libc/sock/recvfrom_test.c @@ -93,3 +93,44 @@ TEST(recvfrom, test) { EXPECT_SYS(0, 0, close(client1)); 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)); +}