diff options
author | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2014-07-08 14:15:23 +0000 |
---|---|---|
committer | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2014-07-08 14:15:23 +0000 |
commit | 54e0edaf51707800948263a1a929cfc64f6df285 (patch) | |
tree | 96896abe99de0c3726b31150ea3e18c1ea807f84 | |
parent | ac3d9556dec854d5a53fa1f53f0d5a3010d7cb56 (diff) | |
download | compiler-rt-54e0edaf51707800948263a1a929cfc64f6df285.tar.gz |
[msan] Fix out of bounds access in origin copying.
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@212534 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/msan/msan_interceptors.cc | 5 | ||||
-rw-r--r-- | lib/msan/tests/msan_test.cc | 82 |
2 files changed, 41 insertions, 46 deletions
diff --git a/lib/msan/msan_interceptors.cc b/lib/msan/msan_interceptors.cc index ba0999a5e..79c7fc17b 100644 --- a/lib/msan/msan_interceptors.cc +++ b/lib/msan/msan_interceptors.cc @@ -1412,6 +1412,9 @@ void CopyOrigin(void *dst, const void *src, uptr size, StackTrace *stack) { } uptr end = (d + size) & ~3UL; + // If both ends fall into the same 4-byte slot, we are done. + if (end < beg) return; + // Copy right unaligned origin if that memory is poisoned. if (end < d + size) { u32 o = GetOriginIfPoisoned((uptr)src + (end - d), (d + size) - end); @@ -1428,7 +1431,7 @@ void CopyOrigin(void *dst, const void *src, uptr size, StackTrace *stack) { if (__msan_get_track_origins() > 1) { u32 *src = (u32 *)MEM_TO_ORIGIN(s); u32 *src_s = (u32 *)MEM_TO_SHADOW(s); - u32 *src_end = src + (end - beg); + u32 *src_end = (u32 *)MEM_TO_ORIGIN(s + (end - beg)); u32 *dst = (u32 *)MEM_TO_ORIGIN(beg); u32 src_o = 0; u32 dst_o = 0; diff --git a/lib/msan/tests/msan_test.cc b/lib/msan/tests/msan_test.cc index c60099637..f7268d68f 100644 --- a/lib/msan/tests/msan_test.cc +++ b/lib/msan/tests/msan_test.cc @@ -1292,64 +1292,56 @@ TEST(MemorySanitizer, memcpy) { EXPECT_POISONED(y[1]); } -// Dst is poisoned, src is clean. -void TestUnalignedMemcpy(int left, int right, bool src_is_aligned) { - const int sz = 20; +void TestUnalignedMemcpy(unsigned left, unsigned right, bool src_is_aligned, + bool src_is_poisoned, bool dst_is_poisoned) { + fprintf(stderr, "%s(%d, %d, %d, %d, %d)\n", __func__, left, right, + src_is_aligned, src_is_poisoned, dst_is_poisoned); + + const unsigned sz = 20; + U4 dst_origin, src_origin; char *dst = (char *)malloc(sz); - U4 origin = __msan_get_origin(dst); + if (dst_is_poisoned) + dst_origin = __msan_get_origin(dst); + else + memset(dst, 0, sz); char *src = (char *)malloc(sz); - memset(src, 0, sz); + if (src_is_poisoned) + src_origin = __msan_get_origin(src); + else + memset(src, 0, sz); memcpy(dst + left, src_is_aligned ? src + left : src, sz - left - right); - for (int i = 0; i < left; ++i) - EXPECT_POISONED_O(dst[i], origin); - for (int i = 0; i < right; ++i) - EXPECT_POISONED_O(dst[sz - i - 1], origin); - EXPECT_NOT_POISONED(dst[left]); - EXPECT_NOT_POISONED(dst[sz - right - 1]); - free(dst); - free(src); -} - -TEST(MemorySanitizer, memcpy_unaligned) { - for (int i = 0; i < 10; ++i) { - for (int j = 0; j < 10; ++j) { - TestUnalignedMemcpy(i, j, true); - TestUnalignedMemcpy(i, j, false); - } - } -} - -// Src is poisoned, dst is clean. -void TestUnalignedPoisonedMemcpy(int left, int right, bool src_is_aligned) { - const int sz = 20; - char *dst = (char *)malloc(sz); - memset(dst, 0, sz); + for (unsigned i = 0; i < (left & (~3U)); ++i) + if (dst_is_poisoned) + EXPECT_POISONED_O(dst[i], dst_origin); + else + EXPECT_NOT_POISONED(dst[i]); - char *src = (char *)malloc(sz); - U4 origin = __msan_get_origin(src); + for (unsigned i = 0; i < (right & (~3U)); ++i) + if (dst_is_poisoned) + EXPECT_POISONED_O(dst[sz - i - 1], dst_origin); + else + EXPECT_NOT_POISONED(dst[sz - i - 1]); - memcpy(dst + left, src_is_aligned ? src + left : src, sz - left - right); - for (int i = 0; i < left; ++i) - EXPECT_NOT_POISONED(dst[i]); - for (int i = 0; i < right; ++i) - EXPECT_NOT_POISONED(dst[sz - i - 1]); - EXPECT_POISONED_O(dst[left], origin); - EXPECT_POISONED_O(dst[sz - right - 1], origin); + for (unsigned i = left; i < sz - right; ++i) + if (src_is_poisoned) + EXPECT_POISONED_O(dst[i], src_origin); + else + EXPECT_NOT_POISONED(dst[i]); free(dst); free(src); } -TEST(MemorySanitizer, memcpy_unaligned_poisoned) { - for (int i = 0; i < 10; ++i) { - for (int j = 0; j < 10; ++j) { - TestUnalignedPoisonedMemcpy(i, j, true); - TestUnalignedPoisonedMemcpy(i, j, false); - } - } +TEST(MemorySanitizer, memcpy_unaligned) { + for (int i = 0; i < 10; ++i) + for (int j = 0; j < 10; ++j) + for (int aligned = 0; aligned < 2; ++aligned) + for (int srcp = 0; srcp < 2; ++srcp) + for (int dstp = 0; dstp < 2; ++dstp) + TestUnalignedMemcpy(i, j, aligned, srcp, dstp); } TEST(MemorySanitizer, memmove) { |