@@ -23,17 +23,26 @@ namespace LIBC_NAMESPACE_DECL {
23
23
24
24
LLVM_LIBC_FUNCTION (ssize_t , recvfrom,
25
25
(int sockfd, void *buf, size_t len, int flags,
26
- struct sockaddr *__restrict dest_addr ,
26
+ sockaddr *__restrict src_addr ,
27
27
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
+
28
37
#ifdef SYS_recvfrom
29
38
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);
31
40
#elif defined(SYS_socketcall)
32
41
unsigned long sockcall_args[6 ] = {static_cast <unsigned long >(sockfd),
33
42
reinterpret_cast <unsigned long >(buf),
34
43
static_cast <unsigned long >(len),
35
44
static_cast <unsigned long >(flags),
36
- reinterpret_cast <unsigned long >(dest_addr ),
45
+ reinterpret_cast <unsigned long >(src_addr ),
37
46
static_cast <unsigned long >(addrlen)};
38
47
ssize_t ret = LIBC_NAMESPACE::syscall_impl<ssize_t >(
39
48
SYS_socketcall, SYS_RECVFROM, sockcall_args);
@@ -46,8 +55,13 @@ LLVM_LIBC_FUNCTION(ssize_t, recvfrom,
46
55
}
47
56
48
57
MSAN_UNPOISON (buf, ret);
49
- MSAN_UNPOISON (addrlen, sizeof (socklen_t ));
50
58
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
+ }
51
65
return ret;
52
66
}
53
67
0 commit comments