diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index 24a8a2d4dc55b..5ba5f254be47f 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -10263,6 +10263,58 @@ INTERCEPTOR(SSIZE_T, freadlink, int fd, char *buf, SIZE_T bufsiz) { # define INIT_FREADLINK #endif +#if SANITIZER_INTERCEPT_GETADDRINFO_A +INTERCEPTOR(int, getaddrinfo_a, int mode, struct __sanitizer_gaicb *list, + int num, void *sevp) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, getaddrinfo_a, mode, list, num, sevp); + if (sevp) + COMMON_INTERCEPTOR_READ_RANGE(ctx, sevp, struct_sigevent_sz); + if (list) { + for (int i = 0; i < num; i++) { + struct __sanitizer_gaicb *cb = list[i]; + COMMON_INTERCEPTOR_READ_RANGE(ctx, cb, sizeof(__sanitizer_gaicb)); + if (cb->ar_name) + COMMON_INTERCEPTOR_READ_RANGE(ctx, cb->ar_name, + internal_strlen(cb->ar_name) + 1); + if (cb->ar_service) + COMMON_INTERCEPTOR_READ_RANGE(ctx, cb->ar_service, + internal_strlen(cb->ar_service) + 1); + if (cb->ar_request) { + COMMON_INTERCEPTOR_READ_RANGE(ctx, cb->ar_request, + sizeof(__sanitizer_addrinfo)); + } + } + } + + int res = REAL(getaddrinfo_a)(mode, list, num, sevp); + if (res == 0 && list) { + for (int i = 0; i < num; i++) { + struct __sanitizer_addrinfo *result = list[i]->ar_result; + if (result) { + while (result) { + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, + sizeof(__sanitizer_addrinfo)); + if (result->ai_addr) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result->ai_addr, + result->ai_addrlen); + if (result->ai_canonname) + COMMON_INTERCEPTOR_WRITE_RANGE( + ctx, result->ai_canonname, + internal_strlen(result->ai_canonname) + 1); + result = result->ai_next; + } + } + } + } + + return res; +} +# define INIT_GETADDRINFO_A COMMON_INTERCEPT_FUNCTION(getaddrinfo_a) +#else +# define INIT_GETADDRINFO_A +#endif + #include "sanitizer_common_interceptors_netbsd_compat.inc" namespace __sanitizer { @@ -10585,6 +10637,7 @@ static void InitializeCommonInterceptors() { INIT_PREADV2; INIT_PWRITEV2; INIT_FREADLINK; + INIT_GETADDRINFO_A; INIT___PRINTF_CHK; } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h index febd233bb1e3c..4f8bde076f848 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -640,6 +640,7 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment, # define SI_MAC_OS_DEPLOYMENT_MIN_13_00 0 #endif #define SANITIZER_INTERCEPT_FREADLINK (SI_MAC && SI_MAC_OS_DEPLOYMENT_MIN_13_00) +#define SANITIZER_GETADDRINFO_A SI_LINUX // This macro gives a way for downstream users to override the above // interceptor macros irrespective of the platform they are on. They have // to do two things: diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp index ddd67cb43524d..bed311608daeb 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp @@ -1172,6 +1172,12 @@ CHECK_TYPE_SIZE(__kernel_old_gid_t); CHECK_TYPE_SIZE(__kernel_off_t); CHECK_TYPE_SIZE(__kernel_loff_t); CHECK_TYPE_SIZE(__kernel_fd_set); + +CHECK_TYPE_SIZE(gaicb); +CHECK_SIZE_AND_OFFSET(gaicb, ar_name); +CHECK_SIZE_AND_OFFSET(gaicb, ar_service); +CHECK_SIZE_AND_OFFSET(gaicb, ar_request); +CHECK_SIZE_AND_OFFSET(gaicb, ar_result); #endif #if !SANITIZER_ANDROID diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h index 7e62dc0e0523e..bafbf5d4b5545 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -788,6 +788,16 @@ struct __sanitizer_addrinfo { struct __sanitizer_addrinfo *ai_next; }; +# if SANITIZER_LINUX +struct __sanitizer_gaicb { + const char *ar_name; + const char *ar_service; + const struct __sanitizer_addrinfo *ar_request; + struct __sanitizer_addrinfo *ar_result; + int __pad[6]; +}; +# endif + struct __sanitizer_hostent { char *h_name; char **h_aliases; diff --git a/compiler-rt/test/msan/Linux/getaddrinfo_a.cpp b/compiler-rt/test/msan/Linux/getaddrinfo_a.cpp new file mode 100644 index 0000000000000..1902057fcdcce --- /dev/null +++ b/compiler-rt/test/msan/Linux/getaddrinfo_a.cpp @@ -0,0 +1,32 @@ +// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && not %run %t >%t.out 2>&1 +// RUN: FileCheck %s < %t.out && FileCheck %s < %t.out + +#include +#include +#include +#include +#include + +int main(void) { + const int nm = 4; + struct gaicb *list[nm]; + + for (auto i = 0; i < nm; i++) { + list[i] = (struct gaicb *)malloc(sizeof(struct gaicb)); + if (i % 2) + memset(list[i], 0, sizeof(struct gaicb)); + list[i]->ar_name = "name"; + } + + int res = getaddrinfo_a(GAI_WAIT, list, nm, NULL); + for (auto i = 0; i < nm; i++) { + // CHECK: WARNING: MemorySanitizer: use-of-uninitialized-value + // CHECK: {{#0 .* in main.*getaddrinfo_a.cpp:25}} + for (auto it = list[i]->ar_result; it; it = it->ai_next) { + auto name = it->ai_canonname; + } + + free(list[i]); + } + return 0; +}