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