Index: test/asan/TestCases/Linux/recvfrom.cc =================================================================== --- test/asan/TestCases/Linux/recvfrom.cc +++ test/asan/TestCases/Linux/recvfrom.cc @@ -2,7 +2,6 @@ // // RUN: %clangxx_asan %s -o %t && not %run %t 2>&1 | FileCheck %s // -// REQUIRES: broken // UNSUPPORTED: android #include @@ -14,26 +13,38 @@ #include #include -const int kPortNum = 1234; +#define CHECK_ERROR(p, m) \ + if (p) { \ + fprintf(stderr, m); \ + exit(1); \ + } + const int kBufSize = 10; +pthread_mutex_t server_ready_mu = PTHREAD_MUTEX_INITIALIZER; static void *server_thread_udp(void *data) { char buf[kBufSize / 2]; - struct sockaddr_in serveraddr; // server's addr + struct sockaddr_in serveraddr; + socklen_t addrlen; int sockfd = socket(AF_INET, SOCK_DGRAM, 0); - if (sockfd < 0) - fprintf(stderr, "ERROR opening socket\n"); + CHECK_ERROR(sockfd < 0, "ERROR opening socket.\n"); - memset((char *) &serveraddr, 0, sizeof(serveraddr)); + memset((char *)&serveraddr, 0, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); - serveraddr.sin_port = htons(kPortNum); + serveraddr.sin_port = htons(0); + + int bound = bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)); + CHECK_ERROR(bound < 0, "ERROR on binding.\n"); - if (bind(sockfd, (struct sockaddr *) &serveraddr, sizeof(serveraddr)) < 0) - fprintf(stderr, "ERROR on binding\n"); + // Provide necessary information (e.g. port number) to client thread. + int succeeded = getsockname(sockfd, (struct sockaddr *)data, &addrlen); + CHECK_ERROR(succeeded < 0, "ERROR in getsockname.\n"); + // Now it's safe to unblock client thread. + pthread_mutex_unlock(&server_ready_mu); recvfrom(sockfd, buf, kBufSize, 0, NULL, NULL); // BOOM - // CHECK: {{WRITE of size 9 at 0x.* thread T1}} + // CHECK: {{WRITE of size 10 at 0x.* thread T1}} // CHECK: {{ #1 0x.* in server_thread_udp.*recvfrom.cc:}}[[@LINE-2]] // CHECK: {{Address 0x.* is located in stack of thread T1 at offset}} // CHECK-NEXT: in{{.*}}server_thread_udp{{.*}}recvfrom.cc @@ -41,39 +52,29 @@ } int main() { - char buf[kBufSize] = "123456789"; - struct sockaddr_in serveraddr; // server's addr - + char buf[kBufSize]; + struct sockaddr_in serveraddr; pthread_t server_thread; - if (pthread_create(&server_thread, NULL, server_thread_udp, NULL)) { - fprintf(stderr, "Error creating thread\n"); - exit(1); - } - int sockfd = socket(AF_INET, SOCK_DGRAM, 0); - struct hostent *server; - char hostname[] = "localhost"; - if (sockfd < 0) - fprintf(stderr, "ERROR opening socket\n"); + memset((char *)&serveraddr, 0, sizeof(serveraddr)); + // Default state for server_ready_mu is 'unlocked'. Lock it to make sure + // following pthread_mutex_lock won't pass before server becomes ready. + pthread_mutex_lock(&server_ready_mu); + int succeeded = pthread_create(&server_thread, NULL, server_thread_udp, + (void *)&serveraddr); + CHECK_ERROR(succeeded, "Error creating thread.\n"); - server = gethostbyname(hostname); - if (!server) { - fprintf(stderr,"ERROR, no such host as %s\n", hostname); - exit(1); - } + int sockfd = socket(AF_INET, SOCK_DGRAM, 0); + CHECK_ERROR(sockfd < 0, "ERROR opening socket.\n"); - memset((char *) &serveraddr, 0, sizeof(serveraddr)); - serveraddr.sin_family = AF_INET; - memcpy((char *)&serveraddr.sin_addr.s_addr, (char *)server->h_addr, - server->h_length); - serveraddr.sin_port = htons(kPortNum); - sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *) &serveraddr, + // Wait for server that should properly initialize serveraddr. + pthread_mutex_lock(&server_ready_mu); + sendto(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&serveraddr, sizeof(serveraddr)); - if (pthread_join(server_thread, NULL)) { - fprintf(stderr, "Error joining thread\n"); - exit(1); - } - + succeeded = pthread_join(server_thread, NULL); + CHECK_ERROR(succeeded, "Error joining thread.\n"); + pthread_mutex_unlock(&server_ready_mu); + pthread_mutex_destroy(&server_ready_mu); return 0; }