xref: /llvm-project/compiler-rt/test/asan/TestCases/Linux/recvfrom.cpp (revision ad81dea9f66db61eed1229cd7e62babb6d381257)
1673dc3d4SNico Weber // Test that ASan detects buffer overflow on read from socket via recvfrom.
2673dc3d4SNico Weber //
3673dc3d4SNico Weber // RUN: %clangxx_asan %s -DRECVFROM -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-RECVFROM
4673dc3d4SNico Weber // RUN: %clangxx_asan %s -DSENDTO -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-SENDTO
5673dc3d4SNico Weber // RUN: %clangxx_asan %s -DSENDTO -o %t && %env_asan_opts=intercept_send=0 %run %t 2>&1
6673dc3d4SNico Weber //
7*ad81dea9SDavid Spickett // This will try to fast unwind on Arm Thumb, where fast unwinding does not work.
8*ad81dea9SDavid Spickett // UNSUPPORTED: android, !fast-unwinder-works
9673dc3d4SNico Weber 
10673dc3d4SNico Weber #include <stdio.h>
11673dc3d4SNico Weber #include <unistd.h>
12673dc3d4SNico Weber #include <stdlib.h>
13673dc3d4SNico Weber #include <string.h>
14673dc3d4SNico Weber #include <netdb.h>
15673dc3d4SNico Weber #include <sys/types.h>
16673dc3d4SNico Weber #include <sys/socket.h>
17673dc3d4SNico Weber #include <pthread.h>
18673dc3d4SNico Weber 
19673dc3d4SNico Weber #define CHECK_ERROR(p, m)                                                      \
20673dc3d4SNico Weber   do {                                                                         \
21673dc3d4SNico Weber     if (p) {                                                                   \
22673dc3d4SNico Weber       fprintf(stderr, "ERROR " m "\n");                                        \
23673dc3d4SNico Weber       exit(1);                                                                 \
24673dc3d4SNico Weber     }                                                                          \
25673dc3d4SNico Weber   } while (0)
26673dc3d4SNico Weber 
27673dc3d4SNico Weber const int kBufSize = 10;
28673dc3d4SNico Weber int sockfd;
29673dc3d4SNico Weber 
client_thread_udp(void * data)30673dc3d4SNico Weber static void *client_thread_udp(void *data) {
31673dc3d4SNico Weber #ifdef SENDTO
32673dc3d4SNico Weber   const char buf[kBufSize / 2] = {0, };
33673dc3d4SNico Weber #else
34673dc3d4SNico Weber   const char buf[kBufSize] = {0, };
35673dc3d4SNico Weber #endif
36673dc3d4SNico Weber   struct sockaddr_in serveraddr;
37673dc3d4SNico Weber   socklen_t addrlen = sizeof(serveraddr);
38673dc3d4SNico Weber 
39673dc3d4SNico Weber   int succeeded = getsockname(sockfd, (struct sockaddr *)&serveraddr, &addrlen);
40673dc3d4SNico Weber   CHECK_ERROR(succeeded < 0, "in getsockname");
41673dc3d4SNico Weber 
42673dc3d4SNico Weber   succeeded = sendto(sockfd, buf, kBufSize, 0, (struct sockaddr *)&serveraddr,
43673dc3d4SNico Weber                      sizeof(serveraddr));
44673dc3d4SNico Weber   // CHECK-SENDTO: {{READ of size 10 at 0x.* thread T1}}
45673dc3d4SNico Weber   // CHECK-SENDTO: {{    #1 0x.* in client_thread_udp.*recvfrom.cpp:}}[[@LINE-3]]
46673dc3d4SNico Weber   CHECK_ERROR(succeeded < 0, "in sending message");
47673dc3d4SNico Weber   return NULL;
48673dc3d4SNico Weber }
49673dc3d4SNico Weber 
main()50673dc3d4SNico Weber int main() {
51673dc3d4SNico Weber #ifdef RECVFROM
52673dc3d4SNico Weber   char buf[kBufSize / 2];
53673dc3d4SNico Weber #else
54673dc3d4SNico Weber   char buf[kBufSize];
55673dc3d4SNico Weber #endif
56673dc3d4SNico Weber   pthread_t client_thread;
57673dc3d4SNico Weber   struct sockaddr_in serveraddr;
58673dc3d4SNico Weber 
59673dc3d4SNico Weber   sockfd = socket(AF_INET, SOCK_DGRAM, 0);
60673dc3d4SNico Weber   CHECK_ERROR(sockfd < 0, "opening socket");
61673dc3d4SNico Weber 
62673dc3d4SNico Weber   memset(&serveraddr, 0, sizeof(serveraddr));
63673dc3d4SNico Weber   serveraddr.sin_family = AF_INET;
64673dc3d4SNico Weber   serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
65673dc3d4SNico Weber   serveraddr.sin_port = 0;
66673dc3d4SNico Weber 
67673dc3d4SNico Weber   int bound = bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
68673dc3d4SNico Weber   CHECK_ERROR(bound < 0, "on binding");
69673dc3d4SNico Weber 
70673dc3d4SNico Weber   int succeeded =
71673dc3d4SNico Weber       pthread_create(&client_thread, NULL, client_thread_udp, &serveraddr);
72673dc3d4SNico Weber   CHECK_ERROR(succeeded, "creating thread");
73673dc3d4SNico Weber 
74673dc3d4SNico Weber   recvfrom(sockfd, buf, kBufSize, 0, NULL, NULL); // BOOM
75673dc3d4SNico Weber   // CHECK-RECVFROM: {{WRITE of size 10 at 0x.* thread T0}}
76673dc3d4SNico Weber   // CHECK-RECVFROM: {{    #1 0x.* in main.*recvfrom.cpp:}}[[@LINE-2]]
77673dc3d4SNico Weber   // CHECK-RECVFROM: {{Address 0x.* is located in stack of thread T0 at offset}}
78673dc3d4SNico Weber   // CHECK-RECVFROM-NEXT: in{{.*}}main{{.*}}recvfrom.cpp
79673dc3d4SNico Weber   succeeded = pthread_join(client_thread, NULL);
80673dc3d4SNico Weber   CHECK_ERROR(succeeded, "joining thread");
81673dc3d4SNico Weber   return 0;
82673dc3d4SNico Weber }
83