@@ -23,17 +23,26 @@ namespace LIBC_NAMESPACE_DECL {
2323
2424LLVM_LIBC_FUNCTION (ssize_t , recvfrom,
2525 (int sockfd, void *buf, size_t len, int flags,
26- struct sockaddr *__restrict dest_addr ,
26+ sockaddr *__restrict src_addr ,
2727 socklen_t *__restrict addrlen)) {
28+ // addrlen is a value-result argument. If it's not null, it passes the max
29+ // size of the buffer src_addr to the syscall. After the syscall, it's updated
30+ // to the actual size of the source address. This may be larger than the
31+ // buffer, in which case the buffer contains a truncated result.
32+ size_t srcaddr_sz;
33+ if (src_addr)
34+ srcaddr_sz = *addrlen;
35+ (void )srcaddr_sz; // prevent "set but not used" warning
36+
2837#ifdef SYS_recvfrom
2938 ssize_t ret = LIBC_NAMESPACE::syscall_impl<ssize_t >(
30- SYS_recvfrom, sockfd, buf, len, flags, dest_addr , addrlen);
39+ SYS_recvfrom, sockfd, buf, len, flags, src_addr , addrlen);
3140#elif defined(SYS_socketcall)
3241 unsigned long sockcall_args[6 ] = {static_cast <unsigned long >(sockfd),
3342 reinterpret_cast <unsigned long >(buf),
3443 static_cast <unsigned long >(len),
3544 static_cast <unsigned long >(flags),
36- reinterpret_cast <unsigned long >(dest_addr ),
45+ reinterpret_cast <unsigned long >(src_addr ),
3746 static_cast <unsigned long >(addrlen)};
3847 ssize_t ret = LIBC_NAMESPACE::syscall_impl<ssize_t >(
3948 SYS_socketcall, SYS_RECVFROM, sockcall_args);
@@ -46,8 +55,13 @@ LLVM_LIBC_FUNCTION(ssize_t, recvfrom,
4655 }
4756
4857 MSAN_UNPOISON (buf, ret);
49- MSAN_UNPOISON (addrlen, sizeof (socklen_t ));
5058
59+ if (src_addr) {
60+ size_t min_src_addr_size = (*addrlen < srcaddr_sz) ? *addrlen : srcaddr_sz;
61+ (void )min_src_addr_size; // prevent "set but not used" warning
62+
63+ MSAN_UNPOISON (src_addr, min_src_addr_size);
64+ }
5165 return ret;
5266}
5367
0 commit comments