diff --git a/compiler-rt/lib/msan/msan_interceptors.cpp b/compiler-rt/lib/msan/msan_interceptors.cpp index dbe18ce37509eb..d745fa7563d90b 100644 --- a/compiler-rt/lib/msan/msan_interceptors.cpp +++ b/compiler-rt/lib/msan/msan_interceptors.cpp @@ -666,6 +666,19 @@ INTERCEPTOR(int, fstat, int fd, void *buf) { #define MSAN_MAYBE_INTERCEPT_FSTAT #endif +#if SANITIZER_STAT_LINUX +INTERCEPTOR(int, fstat64, int fd, void *buf) { + ENSURE_MSAN_INITED(); + int res = REAL(fstat64)(fd, buf); + if (!res) + __msan_unpoison(buf, __sanitizer::struct_stat64_sz); + return res; +} +# define MSAN_MAYBE_INTERCEPT_FSTAT64 MSAN_INTERCEPT_FUNC(fstat64) +#else +# define MSAN_MAYBE_INTERCEPT_FSTAT64 +#endif + #if SANITIZER_GLIBC INTERCEPTOR(int, __fxstat, int magic, int fd, void *buf) { ENSURE_MSAN_INITED(); @@ -704,6 +717,19 @@ INTERCEPTOR(int, fstatat, int fd, char *pathname, void *buf, int flags) { # define MSAN_MAYBE_INTERCEPT_FSTATAT #endif +#if SANITIZER_STAT_LINUX +INTERCEPTOR(int, fstatat64, int fd, char *pathname, void *buf, int flags) { + ENSURE_MSAN_INITED(); + int res = REAL(fstatat64)(fd, pathname, buf, flags); + if (!res) + __msan_unpoison(buf, __sanitizer::struct_stat64_sz); + return res; +} +# define MSAN_MAYBE_INTERCEPT_FSTATAT64 MSAN_INTERCEPT_FUNC(fstatat64) +#else +# define MSAN_MAYBE_INTERCEPT_FSTATAT64 +#endif + #if SANITIZER_GLIBC INTERCEPTOR(int, __fxstatat, int magic, int fd, char *pathname, void *buf, int flags) { @@ -1691,8 +1717,10 @@ void InitializeInterceptors() { INTERCEPT_FUNCTION(gettimeofday); MSAN_MAYBE_INTERCEPT_FCVT; MSAN_MAYBE_INTERCEPT_FSTAT; + MSAN_MAYBE_INTERCEPT_FSTAT64; MSAN_MAYBE_INTERCEPT___FXSTAT; MSAN_MAYBE_INTERCEPT_FSTATAT; + MSAN_MAYBE_INTERCEPT_FSTATAT64; MSAN_MAYBE_INTERCEPT___FXSTATAT; MSAN_MAYBE_INTERCEPT___FXSTAT64; MSAN_MAYBE_INTERCEPT___FXSTATAT64; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index eeeeb1622ff5b9..18b023078441b6 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -6941,6 +6941,23 @@ INTERCEPTOR(int, stat, const char *path, void *buf) { #define INIT_STAT #endif +#if SANITIZER_INTERCEPT_STAT64 +INTERCEPTOR(int, stat64, const char *path, void *buf) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, stat64, path, buf); + if (common_flags()->intercept_stat) + COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0); + int res = REAL(stat64)(path, buf); + if (!res) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz); + return res; +} +#define INIT_STAT64 COMMON_INTERCEPT_FUNCTION(stat64) +#else +#define INIT_STAT64 +#endif + + #if SANITIZER_INTERCEPT_LSTAT INTERCEPTOR(int, lstat, const char *path, void *buf) { void *ctx; @@ -6957,6 +6974,22 @@ INTERCEPTOR(int, lstat, const char *path, void *buf) { #define INIT_LSTAT #endif +#if SANITIZER_INTERCEPT_STAT64 +INTERCEPTOR(int, lstat64, const char *path, void *buf) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, lstat64, path, buf); + if (common_flags()->intercept_stat) + COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0); + int res = REAL(lstat64)(path, buf); + if (!res) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz); + return res; +} +#define INIT_LSTAT64 COMMON_INTERCEPT_FUNCTION(lstat64) +#else +#define INIT_LSTAT64 +#endif + #if SANITIZER_INTERCEPT___XSTAT INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) { void *ctx; @@ -10516,8 +10549,10 @@ static void InitializeCommonInterceptors() { INIT_RECV_RECVFROM; INIT_SEND_SENDTO; INIT_STAT; + INIT_STAT64; INIT_EVENTFD_READ_WRITE; INIT_LSTAT; + INIT_LSTAT64; INIT___XSTAT; INIT___XSTAT64; INIT___LXSTAT; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h index 14610f2df78df5..4c9677d20c0886 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -465,6 +465,7 @@ #define SANITIZER_INTERCEPT_STAT \ (SI_FREEBSD || SI_MAC || SI_ANDROID || SI_NETBSD || SI_SOLARIS || \ SI_STAT_LINUX) +#define SANITIZER_INTERCEPT_STAT64 SI_STAT_LINUX #define SANITIZER_INTERCEPT_LSTAT (SI_NETBSD || SI_FREEBSD || SI_STAT_LINUX) #define SANITIZER_INTERCEPT___XSTAT \ ((!SANITIZER_INTERCEPT_STAT && SI_POSIX) || SI_STAT_LINUX) diff --git a/compiler-rt/test/msan/fstat64.cpp b/compiler-rt/test/msan/fstat64.cpp new file mode 100644 index 00000000000000..8e3a6d553bfcf9 --- /dev/null +++ b/compiler-rt/test/msan/fstat64.cpp @@ -0,0 +1,16 @@ +// REQUIRES: linux +// RUN: %clangxx_msan -O0 %s -o %t && %run %t + +#include +#include + +int main(void) { + struct stat64 st; + if (fstat64(0, &st)) + exit(1); + + if (S_ISBLK(st.st_mode)) + exit(0); + + return 0; +} diff --git a/compiler-rt/test/msan/fstatat64.cpp b/compiler-rt/test/msan/fstatat64.cpp new file mode 100644 index 00000000000000..253299c4566945 --- /dev/null +++ b/compiler-rt/test/msan/fstatat64.cpp @@ -0,0 +1,18 @@ +// REQUIRES: linux +// RUN: %clangxx_msan -O0 %s -o %t && %run %t + +#include +#include +#include +#include + +int main(void) { + struct stat64 st; + int dirfd = open("/dev", O_RDONLY); + if (fstatat64(dirfd, "null", &st, 0)) + exit(1); + + assert(S_ISCHR(st.st_mode)); + + return 0; +} diff --git a/compiler-rt/test/msan/stat64.cpp b/compiler-rt/test/msan/stat64.cpp new file mode 100644 index 00000000000000..a1280a0de37d2e --- /dev/null +++ b/compiler-rt/test/msan/stat64.cpp @@ -0,0 +1,16 @@ +// REQUIRES: linux +// RUN: %clangxx_msan -O0 %s -o %t && %run %t + +#include +#include +#include + +int main(void) { + struct stat64 st; + if (stat64("/dev/null", &st)) + exit(1); + + assert(S_ISCHR(st.st_mode)); + + return 0; +} diff --git a/compiler-rt/test/sanitizer_common/TestCases/Posix/lstat64.cpp b/compiler-rt/test/sanitizer_common/TestCases/Posix/lstat64.cpp new file mode 100644 index 00000000000000..22ab3068274eea --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/Posix/lstat64.cpp @@ -0,0 +1,19 @@ +// REQUIRES: linux +// RUN: %clangxx -O0 -g %s -o %t && %run %t + +#include +#include +#include + +int main(void) { + struct stat64 st; + + assert(!lstat64("/dev/null", &st)); +#if defined(__sun__) && defined(__svr4__) + assert(S_ISLNK(st.st_mode)); +#else + assert(S_ISCHR(st.st_mode)); +#endif + + return 0; +}