diff --git a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp index 5b9e992639f55..57a01396b8123 100644 --- a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp +++ b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp @@ -285,6 +285,45 @@ INTERCEPTOR(int, unlinkat, int fd, const char *pathname, int flag) { return REAL(unlinkat)(fd, pathname, flag); } +INTERCEPTOR(int, stat, const char *pathname, struct stat *s) { + __rtsan_notify_intercepted_call("stat"); + return REAL(stat)(pathname, s); +} + +INTERCEPTOR(int, lstat, const char *pathname, struct stat *s) { + __rtsan_notify_intercepted_call("lstat"); + return REAL(lstat)(pathname, s); +} + +INTERCEPTOR(int, fstat, int fd, struct stat *s) { + __rtsan_notify_intercepted_call("fstat"); + return REAL(fstat)(fd, s); +} + +#if !SANITIZER_APPLE // deprecated for darwin +INTERCEPTOR(int, stat64, const char *pathname, struct stat64 *s) { + __rtsan_notify_intercepted_call("stat64"); + return REAL(stat64)(pathname, s); +} + +INTERCEPTOR(int, lstat64, const char *pathname, struct stat64 *s) { + __rtsan_notify_intercepted_call("lstat64"); + return REAL(lstat64)(pathname, s); +} + +INTERCEPTOR(int, fstat64, int fd, struct stat64 *s) { + __rtsan_notify_intercepted_call("fstat64"); + return REAL(fstat64)(fd, s); +} +#define RTSAN_MAYBE_INTERCEPT_STAT64 INTERCEPT_FUNCTION(stat64) +#define RTSAN_MAYBE_INTERCEPT_LSTAT64 INTERCEPT_FUNCTION(lstat64) +#define RTSAN_MAYBE_INTERCEPT_FSTAT64 INTERCEPT_FUNCTION(fstat64) +#else +#define RTSAN_MAYBE_INTERCEPT_STAT64 +#define RTSAN_MAYBE_INTERCEPT_LSTAT64 +#define RTSAN_MAYBE_INTERCEPT_FSTAT64 +#endif + // Streams INTERCEPTOR(FILE *, fopen, const char *path, const char *mode) { @@ -1437,6 +1476,12 @@ void __rtsan::InitializeInterceptors() { RTSAN_MAYBE_INTERCEPT_READLINKAT; INTERCEPT_FUNCTION(unlink); INTERCEPT_FUNCTION(unlinkat); + INTERCEPT_FUNCTION(stat); + INTERCEPT_FUNCTION(lstat); + INTERCEPT_FUNCTION(fstat); + RTSAN_MAYBE_INTERCEPT_STAT64; + RTSAN_MAYBE_INTERCEPT_LSTAT64; + RTSAN_MAYBE_INTERCEPT_FSTAT64; INTERCEPT_FUNCTION(fopen); RTSAN_MAYBE_INTERCEPT_FOPEN64; RTSAN_MAYBE_INTERCEPT_FREOPEN64; diff --git a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp index d1c5a94c12213..fc5a2f771ddb7 100644 --- a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp +++ b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp @@ -401,7 +401,7 @@ TEST_F(RtsanFileTest, FcntlFlockDiesWhenRealtime) { ASSERT_THAT(fd, Ne(-1)); auto Func = [fd]() { - struct flock lock {}; + struct flock lock{}; lock.l_type = F_RDLCK; lock.l_whence = SEEK_SET; lock.l_start = 0; @@ -735,7 +735,7 @@ TEST(TestRtsanInterceptors, IoctlBehavesWithOutputPointer) { GTEST_SKIP(); } - struct ifreq ifr {}; + struct ifreq ifr{}; strncpy(ifr.ifr_name, ifaddr->ifa_name, IFNAMSIZ - 1); int retval = ioctl(sock, SIOCGIFADDR, &ifr); @@ -875,6 +875,33 @@ TEST_F(RtsanOpenedFileTest, UnlinkatDiesWhenRealtime) { ExpectNonRealtimeSurvival(Func); } +TEST_F(RtsanOpenedFileTest, StatDiesWhenRealtime) { + auto Func = [&]() { + struct stat s{}; + stat(GetTemporaryFilePath(), &s); + }; + ExpectRealtimeDeath(Func, MAYBE_APPEND_64("stat")); + ExpectNonRealtimeSurvival(Func); +} + +TEST_F(RtsanOpenedFileTest, LstatDiesWhenRealtime) { + auto Func = [&]() { + struct stat s{}; + lstat(GetTemporaryFilePath(), &s); + }; + ExpectRealtimeDeath(Func, MAYBE_APPEND_64("lstat")); + ExpectNonRealtimeSurvival(Func); +} + +TEST_F(RtsanOpenedFileTest, FstatDiesWhenRealtime) { + auto Func = [&]() { + struct stat s{}; + fstat(GetOpenFd(), &s); + }; + ExpectRealtimeDeath(Func, MAYBE_APPEND_64("fstat")); + ExpectNonRealtimeSurvival(Func); +} + TEST_F(RtsanFileTest, FcloseDiesWhenRealtime) { FILE *f = fopen(GetTemporaryFilePath(), "w"); EXPECT_THAT(f, Ne(nullptr));