1// RUN: %clangxx_msan %s -DSEND -DPOISON -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SEND
2// RUN: %clangxx_msan %s -DSENDTO -DPOISON -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDTO
3// RUN: %clangxx_msan %s -DSENDMSG -DPOISON -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDMSG
4// RUN: %clangxx_msan %s -DSENDMMSG -DPOISON -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDMMSG
5
6// RUN: %clangxx_msan %s -DSEND -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE
7// RUN: %clangxx_msan %s -DSENDTO -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE
8// RUN: %clangxx_msan %s -DSENDMSG -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE
9// RUN: %clangxx_msan %s -DSENDMMSG -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE
10
11// RUN: %clangxx_msan %s -DSEND -DPOISON -o %t && \
12// RUN: MSAN_OPTIONS=intercept_send=0 %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE
13// RUN: %clangxx_msan %s -DSENDTO -DPOISON -o %t && \
14// RUN: MSAN_OPTIONS=intercept_send=0 %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE
15// RUN: %clangxx_msan %s -DSENDMSG -DPOISON -o %t && \
16// RUN: MSAN_OPTIONS=intercept_send=0 %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE
17// RUN: %clangxx_msan %s -DSENDMMSG -DPOISON -o %t && \
18// RUN: MSAN_OPTIONS=intercept_send=0 %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE
19
20// UNSUPPORTED: android
21
22#include <assert.h>
23#include <stdio.h>
24#include <unistd.h>
25#include <stdlib.h>
26#include <string.h>
27#include <sys/types.h>
28#include <sys/socket.h>
29#include <sanitizer/msan_interface.h>
30
31const int kBufSize = 10;
32const int kRecvBufSize = 100;
33int sockfd[2];
34
35int main() {
36 int ret;
37 int sent;
38 char buf[kBufSize] = {0};
39 char rbuf[kRecvBufSize];
40
41 ret = socketpair(AF_LOCAL, SOCK_DGRAM, protocol: 0, fds: sockfd);
42 assert(!ret);
43
44#if defined(POISON)
45 __msan_poison(buf + 7, 1);
46#endif
47
48#if defined(SENDMSG) || defined(SENDMMSG)
49 struct iovec iov[2] = {{buf, 5}, {buf + 5, 5}};
50 struct msghdr msg;
51 msg.msg_name = nullptr;
52 msg.msg_namelen = 0;
53 msg.msg_iov = iov;
54 msg.msg_iovlen = 2;
55 msg.msg_control = 0;
56 msg.msg_controllen = 0;
57 msg.msg_flags = 0;
58#endif
59
60#if defined(SENDMMSG)
61 struct iovec iov0[1] = {{buf, 7}};
62 struct msghdr msg0;
63 msg0.msg_name = nullptr;
64 msg0.msg_namelen = 0;
65 msg0.msg_iov = iov0;
66 msg0.msg_iovlen = 1;
67 msg0.msg_control = 0;
68 msg0.msg_controllen = 0;
69 msg0.msg_flags = 0;
70
71 struct mmsghdr mmsg[2];
72 mmsg[0].msg_hdr = msg0; // good
73 mmsg[1].msg_hdr = msg; // poisoned
74#endif
75
76#if defined(SEND)
77 sent = send(sockfd[0], buf, kBufSize, 0);
78 // SEND: Uninitialized bytes in send at offset 7 inside [{{.*}}, 10)
79 assert(sent > 0);
80
81 ret = recv(sockfd[1], rbuf, kRecvBufSize, 0);
82 assert(ret == sent);
83 assert(__msan_test_shadow(rbuf, kRecvBufSize) == sent);
84#elif defined(SENDTO)
85 sent = sendto(sockfd[0], buf, kBufSize, 0, nullptr, 0);
86 // SENDTO: Uninitialized bytes in sendto at offset 7 inside [{{.*}}, 10)
87 assert(sent > 0);
88
89 struct sockaddr_storage ss;
90 socklen_t sslen = sizeof(ss);
91 ret = recvfrom(sockfd[1], rbuf, kRecvBufSize, 0, (struct sockaddr *)&ss,
92 &sslen);
93 assert(ret == sent);
94 assert(__msan_test_shadow(rbuf, kRecvBufSize) == sent);
95 assert(__msan_test_shadow(&ss, sizeof(ss)) == sslen);
96#elif defined(SENDMSG)
97 sent = sendmsg(sockfd[0], &msg, 0);
98 // SENDMSG: Uninitialized bytes in {{.*}} at offset 2 inside [{{.*}}, 5)
99 assert(sent > 0);
100
101 struct iovec riov[2] = {{rbuf, 3}, {rbuf + 3, kRecvBufSize - 3}};
102 struct msghdr rmsg;
103 rmsg.msg_name = nullptr;
104 rmsg.msg_namelen = 0;
105 rmsg.msg_iov = riov;
106 rmsg.msg_iovlen = 2;
107 rmsg.msg_control = 0;
108 rmsg.msg_controllen = 0;
109 rmsg.msg_flags = 0;
110
111 ret = recvmsg(sockfd[1], &rmsg, 0);
112 assert(ret == sent);
113 assert(__msan_test_shadow(rbuf, kRecvBufSize) == sent);
114#elif defined(SENDMMSG)
115 sent = sendmmsg(sockfd[0], mmsg, 2, 0);
116 // SENDMMSG: Uninitialized bytes in {{.*}} at offset 2 inside [{{.*}}, 5)
117 assert(sent == 2);
118 if (ret >= 2)
119 assert(mmsg[1].msg_len > 0);
120
121 struct iovec riov[2] = {{rbuf + kRecvBufSize / 2, kRecvBufSize / 2}};
122 struct msghdr rmsg;
123 rmsg.msg_name = nullptr;
124 rmsg.msg_namelen = 0;
125 rmsg.msg_iov = riov;
126 rmsg.msg_iovlen = 1;
127 rmsg.msg_control = 0;
128 rmsg.msg_controllen = 0;
129 rmsg.msg_flags = 0;
130
131 struct iovec riov0[2] = {{rbuf, kRecvBufSize / 2}};
132 struct msghdr rmsg0;
133 rmsg0.msg_name = nullptr;
134 rmsg0.msg_namelen = 0;
135 rmsg0.msg_iov = riov0;
136 rmsg0.msg_iovlen = 1;
137 rmsg0.msg_control = 0;
138 rmsg0.msg_controllen = 0;
139 rmsg0.msg_flags = 0;
140
141 struct mmsghdr rmmsg[2];
142 rmmsg[0].msg_hdr = rmsg0;
143 rmmsg[1].msg_hdr = rmsg;
144
145 ret = recvmmsg(sockfd[1], rmmsg, 2, 0, nullptr);
146 assert(ret == sent);
147 assert(__msan_test_shadow(rbuf, kRecvBufSize) == 7);
148 assert(__msan_test_shadow(rbuf + kRecvBufSize / 2, kRecvBufSize / 2) == 10);
149#endif
150 fprintf(stderr, format: "== done\n");
151 // NEGATIVE: == done
152 return 0;
153}
154

source code of compiler-rt/test/msan/Linux/sendmsg.cpp