diff --git a/compiler-rt/lib/msan/msan_interceptors.cc b/compiler-rt/lib/msan/msan_interceptors.cc index 13c922841eb2..d6ae53d1d5ce 100644 --- a/compiler-rt/lib/msan/msan_interceptors.cc +++ b/compiler-rt/lib/msan/msan_interceptors.cc @@ -284,11 +284,10 @@ INTERCEPTOR(char *, strcat, char *dest, const char *src) { // NOLINT INTERCEPTOR(char *, strncat, char *dest, const char *src, SIZE_T n) { // NOLINT ENSURE_MSAN_INITED(); SIZE_T dest_size = REAL(strlen)(dest); - SIZE_T copy_size = REAL(strlen)(src); - if (copy_size < n) - copy_size++; // trailing \0 + SIZE_T copy_size = REAL(strnlen)(src, n); char *res = REAL(strncat)(dest, src, n); // NOLINT __msan_copy_poison(dest + dest_size, src, copy_size); + __msan_unpoison(dest + dest_size + copy_size, 1); // \0 return res; } diff --git a/compiler-rt/lib/msan/tests/msan_test.cc b/compiler-rt/lib/msan/tests/msan_test.cc index a60a232110ed..66e5274e588a 100644 --- a/compiler-rt/lib/msan/tests/msan_test.cc +++ b/compiler-rt/lib/msan/tests/msan_test.cc @@ -1470,6 +1470,45 @@ TEST(MemorySanitizer, stpcpy) { // NOLINT EXPECT_NOT_POISONED(y[2]); } +TEST(MemorySanitizer, strcat) { // NOLINT + char a[10]; + char b[] = "def"; + strcpy(a, "abc"); + __msan_poison(b + 1, 1); + strcat(a, b); + EXPECT_NOT_POISONED(a[3]); + EXPECT_POISONED(a[4]); + EXPECT_NOT_POISONED(a[5]); + EXPECT_NOT_POISONED(a[6]); + EXPECT_POISONED(a[7]); +} + +TEST(MemorySanitizer, strncat) { // NOLINT + char a[10]; + char b[] = "def"; + strcpy(a, "abc"); + __msan_poison(b + 1, 1); + strncat(a, b, 5); + EXPECT_NOT_POISONED(a[3]); + EXPECT_POISONED(a[4]); + EXPECT_NOT_POISONED(a[5]); + EXPECT_NOT_POISONED(a[6]); + EXPECT_POISONED(a[7]); +} + +TEST(MemorySanitizer, strncat_overflow) { // NOLINT + char a[10]; + char b[] = "def"; + strcpy(a, "abc"); + __msan_poison(b + 1, 1); + strncat(a, b, 2); + EXPECT_NOT_POISONED(a[3]); + EXPECT_POISONED(a[4]); + EXPECT_NOT_POISONED(a[5]); + EXPECT_POISONED(a[6]); + EXPECT_POISONED(a[7]); +} + TEST(MemorySanitizer, strtol) { char *e; assert(1 == strtol("1", &e, 10));