diff --git a/compiler-rt/lib/msan/tests/msan_test.cpp b/compiler-rt/lib/msan/tests/msan_test.cpp --- a/compiler-rt/lib/msan/tests/msan_test.cpp +++ b/compiler-rt/lib/msan/tests/msan_test.cpp @@ -3760,6 +3760,18 @@ ASSERT_STREQ("c", w.we_wordv[2]); } +TEST(MemorySanitizer, wordexp_initial_offset) { + wordexp_t w; + w.we_offs = 1; + int res = wordexp("a b c", &w, WRDE_DOOFFS); + ASSERT_EQ(0, res); + ASSERT_EQ(3U, w.we_wordc); + ASSERT_EQ(nullptr, w.we_wordv[0]); + ASSERT_STREQ("a", w.we_wordv[1]); + ASSERT_STREQ("b", w.we_wordv[2]); + ASSERT_STREQ("c", w.we_wordv[3]); +} + template static bool applySlt(T value, T shadow) { __msan_partial_poison(&value, &shadow, sizeof(T)); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -3996,10 +3996,12 @@ int res = REAL(wordexp)(s, p, flags); if (!res && p) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p)); - if (p->we_wordc) + uptr we_wordc = + ((flags & wordexp_wrde_dooffs) ? p->we_wordc : 0) + p->we_wordc; + if (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) { + sizeof(*p->we_wordv) * we_wordc); + for (uptr i = 0; i < we_wordc; ++i) { char *w = p->we_wordv[i]; if (w) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, w, internal_strlen(w) + 1); } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -776,6 +776,10 @@ extern unsigned path_max; +# if !SANITIZER_ANDROID +extern const int wordexp_wrde_dooffs; +# endif // !SANITIZER_ANDROID + struct __sanitizer_wordexp_t { uptr we_wordc; char **we_wordv; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp @@ -313,6 +313,10 @@ int glob_altdirfunc = GLOB_ALTDIRFUNC; #endif +# if !SANITIZER_ANDROID + const int wordexp_wrde_dooffs = WRDE_DOOFFS; +# endif // !SANITIZER_ANDROID + #if SANITIZER_LINUX && !SANITIZER_ANDROID && \ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \