diff --git a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp index 9f89ab6bf1fc7..227d077290af7 100644 --- a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp +++ b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp @@ -325,6 +325,37 @@ INTERCEPTOR(FILE *, fmemopen, void *buf, size_t size, const char *mode) { #define RTSAN_MAYBE_INTERCEPT_FMEMOPEN #endif +#if SANITIZER_INTERCEPT_SETVBUF +INTERCEPTOR(void, setbuf, FILE *stream, char *buf) { + __rtsan_notify_intercepted_call("setbuf"); + return REAL(setbuf)(stream, buf); +} + +INTERCEPTOR(void, setbuffer, FILE *stream, char *buf, size_t size) { + __rtsan_notify_intercepted_call("setbuffer"); + return REAL(setbuffer)(stream, buf, size); +} + +INTERCEPTOR(void, setlinebuf, FILE *stream) { + __rtsan_notify_intercepted_call("setlinebuf"); + return REAL(setlinebuf)(stream); +} + +INTERCEPTOR(int, setvbuf, FILE *stream, char *buf, int mode, size_t size) { + __rtsan_notify_intercepted_call("setvbuf"); + return REAL(setvbuf)(stream, buf, mode, size); +} +#define RTSAN_MAYBE_INTERCEPT_SETBUF INTERCEPT_FUNCTION(setbuf) +#define RTSAN_MAYBE_INTERCEPT_SETBUFFER INTERCEPT_FUNCTION(setbuffer) +#define RTSAN_MAYBE_INTERCEPT_SETLINEBUF INTERCEPT_FUNCTION(setlinebuf) +#define RTSAN_MAYBE_INTERCEPT_SETVBUF INTERCEPT_FUNCTION(setvbuf) +#else +#define RTSAN_MAYBE_INTERCEPT_SETBUF +#define RTSAN_MAYBE_INTERCEPT_SETBUFFER +#define RTSAN_MAYBE_INTERCEPT_SETLINEBUF +#define RTSAN_MAYBE_INTERCEPT_SETVBUF +#endif + INTERCEPTOR(int, puts, const char *s) { __rtsan_notify_intercepted_call("puts"); return REAL(puts)(s); @@ -986,6 +1017,10 @@ void __rtsan::InitializeInterceptors() { RTSAN_MAYBE_INTERCEPT_FOPENCOOKIE; RTSAN_MAYBE_INTERCEPT_OPEN_MEMSTREAM; RTSAN_MAYBE_INTERCEPT_FMEMOPEN; + RTSAN_MAYBE_INTERCEPT_SETBUF; + RTSAN_MAYBE_INTERCEPT_SETBUFFER; + RTSAN_MAYBE_INTERCEPT_SETLINEBUF; + RTSAN_MAYBE_INTERCEPT_SETVBUF; INTERCEPT_FUNCTION(lseek); RTSAN_MAYBE_INTERCEPT_LSEEK64; INTERCEPT_FUNCTION(dup); 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 5adbf0fb63de8..2947510b2cfde 100644 --- a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp +++ b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp @@ -403,6 +403,56 @@ TEST_F(RtsanFileTest, FmemOpenDiesWhenRealtime) { } #endif +#if SANITIZER_INTERCEPT_SETVBUF +TEST_F(RtsanFileTest, SetbufDieWhenRealtime) { + char buffer[BUFSIZ]; + FILE *f = fopen(GetTemporaryFilePath(), "w"); + EXPECT_THAT(f, Ne(nullptr)); + + auto Func = [&f, &buffer]() { setbuf(f, buffer); }; + + ExpectRealtimeDeath(Func, "setbuf"); + ExpectNonRealtimeSurvival(Func); +} + +TEST_F(RtsanFileTest, SetbufferDieWhenRealtime) { + char buffer[1024]; + size_t size = sizeof(buffer); + FILE *f = fopen(GetTemporaryFilePath(), "w"); + EXPECT_THAT(f, Ne(nullptr)); + + auto Func = [&f, &buffer, &size]() { setbuffer(f, buffer, size); }; + + ExpectRealtimeDeath(Func, "setbuffer"); + ExpectNonRealtimeSurvival(Func); +} + +TEST_F(RtsanFileTest, SetvbufDieWhenRealtime) { + char buffer[1024]; + size_t size = sizeof(buffer); + FILE *f = fopen(GetTemporaryFilePath(), "w"); + EXPECT_THAT(f, Ne(nullptr)); + + auto Func = [&f, &buffer, &size]() { + int r = setvbuf(f, buffer, _IOFBF, size); + EXPECT_THAT(r, Eq(0)); + }; + + ExpectRealtimeDeath(Func, "setvbuf"); + ExpectNonRealtimeSurvival(Func); +} + +TEST_F(RtsanFileTest, SetlinebufDieWhenRealtime) { + FILE *f = fopen(GetTemporaryFilePath(), "w"); + EXPECT_THAT(f, Ne(nullptr)); + + auto Func = [&f]() { setlinebuf(f); }; + + ExpectRealtimeDeath(Func, "setlinebuf"); + ExpectNonRealtimeSurvival(Func); +} +#endif + class RtsanOpenedFileTest : public RtsanFileTest { protected: void SetUp() override {