[sanitizer] Intercept wordexp.
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@191305 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/msan/tests/msan_test.cc b/lib/msan/tests/msan_test.cc
index d907fe7..626d566 100644
--- a/lib/msan/tests/msan_test.cc
+++ b/lib/msan/tests/msan_test.cc
@@ -49,6 +49,7 @@
#include <pwd.h>
#include <sys/socket.h>
#include <netdb.h>
+#include <wordexp.h>
#if defined(__i386__) || defined(__x86_64__)
# include <emmintrin.h>
@@ -2400,6 +2401,16 @@
EXPECT_NOT_POISONED(gids[i]);
}
+TEST(MemorySanitizer, wordexp) {
+ wordexp_t w;
+ int res = wordexp("a b c", &w, 0);
+ ASSERT_EQ(0, res);
+ ASSERT_EQ(3, w.we_wordc);
+ ASSERT_STREQ("a", w.we_wordv[0]);
+ ASSERT_STREQ("b", w.we_wordv[1]);
+ ASSERT_STREQ("c", w.we_wordv[2]);
+}
+
template<class T>
static bool applySlt(T value, T shadow) {
__msan_partial_poison(&value, &shadow, sizeof(T));
diff --git a/lib/sanitizer_common/sanitizer_common_interceptors.inc b/lib/sanitizer_common/sanitizer_common_interceptors.inc
index 0322f2b..281ae77 100644
--- a/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -1995,6 +1995,29 @@
#define INIT_PPOLL
#endif
+#if SANITIZER_INTERCEPT_WORDEXP
+INTERCEPTOR(int, wordexp, char *s, __sanitizer_wordexp_t *p, int flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, wordexp, s, p, flags);
+ if (s) COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
+ int res = REAL(wordexp)(s, p, flags);
+ if (!res && p) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
+ if (p->we_wordc)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->we_wordv,
+ sizeof(*p->we_wordv) * p->we_wordc);
+ for (uptr i = 0; i < p->we_wordc; ++i) {
+ char *w = p->we_wordv[i];
+ if (w) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, w, REAL(strlen)(w) + 1);
+ }
+ }
+ return res;
+}
+#define INIT_WORDEXP INTERCEPT_FUNCTION(wordexp);
+#else
+#define INIT_WORDEXP
+#endif
+
#define SANITIZER_COMMON_INTERCEPTORS_INIT \
INIT_STRCMP; \
INIT_STRNCMP; \
@@ -2063,4 +2086,5 @@
INIT_SCANDIR64; \
INIT_GETGROUPS; \
INIT_POLL; \
- INIT_PPOLL;
+ INIT_PPOLL; \
+ INIT_WORDEXP;
diff --git a/lib/sanitizer_common/sanitizer_platform_interceptors.h b/lib/sanitizer_common/sanitizer_platform_interceptors.h
index 854e3ad..cdc1121 100644
--- a/lib/sanitizer_common/sanitizer_platform_interceptors.h
+++ b/lib/sanitizer_common/sanitizer_platform_interceptors.h
@@ -118,5 +118,6 @@
# define SANITIZER_INTERCEPT_GETGROUPS SI_NOT_WINDOWS
# define SANITIZER_INTERCEPT_POLL SI_NOT_WINDOWS
# define SANITIZER_INTERCEPT_PPOLL SI_LINUX_NOT_ANDROID
+# define SANITIZER_INTERCEPT_WORDEXP SI_MAC || SI_LINUX_NOT_ANDROID
#endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H
diff --git a/lib/sanitizer_common/sanitizer_platform_limits_posix.cc b/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
index 3c8abca..212828a 100644
--- a/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
+++ b/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
@@ -42,6 +42,7 @@
#include <termios.h>
#include <time.h>
#include <wchar.h>
+#include <wordexp.h>
#if SANITIZER_LINUX
#include <utime.h>
@@ -874,4 +875,9 @@
CHECK_TYPE_SIZE(__kernel_fd_set);
#endif
+CHECK_TYPE_SIZE(wordexp_t);
+CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordc);
+CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordv);
+CHECK_SIZE_AND_OFFSET(wordexp_t, we_offs);
+
#endif // SANITIZER_LINUX || SANITIZER_MAC
diff --git a/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/lib/sanitizer_common/sanitizer_platform_limits_posix.h
index 659608f..2893ca7 100644
--- a/lib/sanitizer_common/sanitizer_platform_limits_posix.h
+++ b/lib/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -286,6 +286,12 @@
extern unsigned path_max;
+ struct __sanitizer_wordexp_t {
+ uptr we_wordc;
+ char **we_wordv;
+ uptr we_offs;
+ };
+
#if SANITIZER_LINUX && !SANITIZER_ANDROID && \
(defined(__i386) || defined (__x86_64)) // NOLINT
extern unsigned struct_user_regs_struct_sz;
diff --git a/lib/tsan/rtl/tsan_stat.cc b/lib/tsan/rtl/tsan_stat.cc
index ed8b876..2809a75 100644
--- a/lib/tsan/rtl/tsan_stat.cc
+++ b/lib/tsan/rtl/tsan_stat.cc
@@ -361,6 +361,7 @@
name[StatInt_scandir] = " scandir ";
name[StatInt_scandir64] = " scandir64 ";
name[StatInt_getgroups] = " getgroups ";
+ name[StatInt_wordexp] = " wordexp ";
name[StatAnnotation] = "Dynamic annotations ";
name[StatAnnotateHappensBefore] = " HappensBefore ";
diff --git a/lib/tsan/rtl/tsan_stat.h b/lib/tsan/rtl/tsan_stat.h
index d3c0605..fe8af85 100644
--- a/lib/tsan/rtl/tsan_stat.h
+++ b/lib/tsan/rtl/tsan_stat.h
@@ -356,6 +356,7 @@
StatInt_scandir,
StatInt_scandir64,
StatInt_getgroups,
+ StatInt_wordexp,
// Dynamic annotations.
StatAnnotation,