diff --git a/compiler-rt/lib/msan/msan.cc b/compiler-rt/lib/msan/msan.cc index 83b11e5c2ff3..4a484520a583 100644 --- a/compiler-rt/lib/msan/msan.cc +++ b/compiler-rt/lib/msan/msan.cc @@ -33,9 +33,14 @@ static THREADLOCAL int msan_expected_umr_found = 0; static int msan_running_under_dr = 0; +// Function argument shadow. Each argument starts at the next available 8-byte +// aligned address. SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL u64 __msan_param_tls[kMsanParamTlsSizeInWords]; +// Function argument origin. Each argument starts at the same offset as the +// corresponding shadow in (__msan_param_tls). Slightly weird, but changing this +// would break compatibility with older prebuilt binaries. SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL u32 __msan_param_origin_tls[kMsanParamTlsSizeInWords]; @@ -460,8 +465,8 @@ void __msan_set_origin(const void *a, uptr size, u32 origin) { uptr beg = x & ~3UL; // align down. uptr end = (x + size + 3) & ~3UL; // align up. u64 origin64 = ((u64)origin << 32) | origin; - // This is like memset, but the value is 32-bit. We unroll by 2 two write - // 64-bits at once. May want to unroll further to get 128-bit stores. + // This is like memset, but the value is 32-bit. We unroll by 2 to write + // 64 bits at once. May want to unroll further to get 128-bit stores. if (beg & 7ULL) { *(u32*)beg = origin; beg += 4; @@ -521,37 +526,40 @@ u32 __msan_get_umr_origin() { u16 __sanitizer_unaligned_load16(const uu16 *p) { __msan_retval_tls[0] = *(uu16 *)MEM_TO_SHADOW((uptr)p); if (__msan_get_track_origins()) - __msan_retval_origin_tls = *(uu32 *)MEM_TO_ORIGIN((uptr)p); + __msan_retval_origin_tls = *(uu32 *)(MEM_TO_ORIGIN((uptr)p) & ~3UL); return *p; } u32 __sanitizer_unaligned_load32(const uu32 *p) { __msan_retval_tls[0] = *(uu32 *)MEM_TO_SHADOW((uptr)p); if (__msan_get_track_origins()) - __msan_retval_origin_tls = *(uu32 *)MEM_TO_ORIGIN((uptr)p); + __msan_retval_origin_tls = *(uu32 *)(MEM_TO_ORIGIN((uptr)p) & ~3UL); return *p; } u64 __sanitizer_unaligned_load64(const uu64 *p) { __msan_retval_tls[0] = *(uu64 *)MEM_TO_SHADOW((uptr)p); if (__msan_get_track_origins()) - __msan_retval_origin_tls = *(uu32 *)MEM_TO_ORIGIN((uptr)p); + __msan_retval_origin_tls = *(uu32 *)(MEM_TO_ORIGIN((uptr)p) & ~3UL); return *p; } void __sanitizer_unaligned_store16(uu16 *p, u16 x) { *(uu16 *)MEM_TO_SHADOW((uptr)p) = __msan_param_tls[1]; if (__msan_get_track_origins()) - *(uu32 *)MEM_TO_ORIGIN((uptr)p) = __msan_param_origin_tls[1]; + if (uu32 o = __msan_param_origin_tls[2]) + __msan_set_origin(p, 2, o); *p = x; } void __sanitizer_unaligned_store32(uu32 *p, u32 x) { *(uu32 *)MEM_TO_SHADOW((uptr)p) = __msan_param_tls[1]; if (__msan_get_track_origins()) - *(uu32 *)MEM_TO_ORIGIN((uptr)p) = __msan_param_origin_tls[1]; + if (uu32 o = __msan_param_origin_tls[2]) + __msan_set_origin(p, 4, o); *p = x; } void __sanitizer_unaligned_store64(uu64 *p, u64 x) { *(uu64 *)MEM_TO_SHADOW((uptr)p) = __msan_param_tls[1]; if (__msan_get_track_origins()) - *(uu32 *)MEM_TO_ORIGIN((uptr)p) = __msan_param_origin_tls[1]; + if (uu32 o = __msan_param_origin_tls[2]) + __msan_set_origin(p, 8, o); *p = x; } diff --git a/compiler-rt/lib/msan/tests/msan_test.cc b/compiler-rt/lib/msan/tests/msan_test.cc index f95bb4e7c618..e555fec0beff 100644 --- a/compiler-rt/lib/msan/tests/msan_test.cc +++ b/compiler-rt/lib/msan/tests/msan_test.cc @@ -3085,79 +3085,91 @@ TEST(MemorySanitizer, VolatileBitfield) { TEST(MemorySanitizer, UnalignedLoad) { char x[32]; + U4 origin = __LINE__; + __msan_set_origin(&x, sizeof(x), origin); + memset(x + 8, 0, 16); - EXPECT_POISONED(__sanitizer_unaligned_load16(x+6)); - EXPECT_POISONED(__sanitizer_unaligned_load16(x+7)); + EXPECT_POISONED_O(__sanitizer_unaligned_load16(x+6), origin); + EXPECT_POISONED_O(__sanitizer_unaligned_load16(x+7), origin); EXPECT_NOT_POISONED(__sanitizer_unaligned_load16(x+8)); EXPECT_NOT_POISONED(__sanitizer_unaligned_load16(x+9)); EXPECT_NOT_POISONED(__sanitizer_unaligned_load16(x+22)); - EXPECT_POISONED(__sanitizer_unaligned_load16(x+23)); - EXPECT_POISONED(__sanitizer_unaligned_load16(x+24)); + EXPECT_POISONED_O(__sanitizer_unaligned_load16(x+23), origin); + EXPECT_POISONED_O(__sanitizer_unaligned_load16(x+24), origin); - EXPECT_POISONED(__sanitizer_unaligned_load32(x+4)); - EXPECT_POISONED(__sanitizer_unaligned_load32(x+7)); + EXPECT_POISONED_O(__sanitizer_unaligned_load32(x+4), origin); + EXPECT_POISONED_O(__sanitizer_unaligned_load32(x+7), origin); EXPECT_NOT_POISONED(__sanitizer_unaligned_load32(x+8)); EXPECT_NOT_POISONED(__sanitizer_unaligned_load32(x+9)); EXPECT_NOT_POISONED(__sanitizer_unaligned_load32(x+20)); - EXPECT_POISONED(__sanitizer_unaligned_load32(x+21)); - EXPECT_POISONED(__sanitizer_unaligned_load32(x+24)); + EXPECT_POISONED_O(__sanitizer_unaligned_load32(x+21), origin); + EXPECT_POISONED_O(__sanitizer_unaligned_load32(x+24), origin); - EXPECT_POISONED(__sanitizer_unaligned_load64(x)); - EXPECT_POISONED(__sanitizer_unaligned_load64(x+1)); - EXPECT_POISONED(__sanitizer_unaligned_load64(x+7)); + EXPECT_POISONED_O(__sanitizer_unaligned_load64(x), origin); + EXPECT_POISONED_O(__sanitizer_unaligned_load64(x+1), origin); + EXPECT_POISONED_O(__sanitizer_unaligned_load64(x+7), origin); EXPECT_NOT_POISONED(__sanitizer_unaligned_load64(x+8)); EXPECT_NOT_POISONED(__sanitizer_unaligned_load64(x+9)); EXPECT_NOT_POISONED(__sanitizer_unaligned_load64(x+16)); - EXPECT_POISONED(__sanitizer_unaligned_load64(x+17)); - EXPECT_POISONED(__sanitizer_unaligned_load64(x+21)); - EXPECT_POISONED(__sanitizer_unaligned_load64(x+24)); + EXPECT_POISONED_O(__sanitizer_unaligned_load64(x+17), origin); + EXPECT_POISONED_O(__sanitizer_unaligned_load64(x+21), origin); + EXPECT_POISONED_O(__sanitizer_unaligned_load64(x+24), origin); } TEST(MemorySanitizer, UnalignedStore16) { char x[5]; - U2 y = 0; - __msan_poison(&y, 1); - __sanitizer_unaligned_store16(x + 1, y); - EXPECT_POISONED(x[0]); - EXPECT_POISONED(x[1]); + U2 y2 = 0; + U4 origin = __LINE__; + __msan_poison(&y2, 1); + __msan_set_origin(&y2, 1, origin); + + __sanitizer_unaligned_store16(x + 1, y2); + EXPECT_POISONED_O(x[0], origin); + EXPECT_POISONED_O(x[1], origin); EXPECT_NOT_POISONED(x[2]); - EXPECT_POISONED(x[3]); - EXPECT_POISONED(x[4]); + EXPECT_POISONED_O(x[3], origin); + EXPECT_POISONED_O(x[4], origin); } TEST(MemorySanitizer, UnalignedStore32) { char x[8]; U4 y4 = 0; + U4 origin = __LINE__; __msan_poison(&y4, 2); + __msan_set_origin(&y4, 2, origin); + __sanitizer_unaligned_store32(x+3, y4); - EXPECT_POISONED(x[0]); - EXPECT_POISONED(x[1]); - EXPECT_POISONED(x[2]); - EXPECT_POISONED(x[3]); - EXPECT_POISONED(x[4]); + EXPECT_POISONED_O(x[0], origin); + EXPECT_POISONED_O(x[1], origin); + EXPECT_POISONED_O(x[2], origin); + EXPECT_POISONED_O(x[3], origin); + EXPECT_POISONED_O(x[4], origin); EXPECT_NOT_POISONED(x[5]); EXPECT_NOT_POISONED(x[6]); - EXPECT_POISONED(x[7]); + EXPECT_POISONED_O(x[7], origin); } TEST(MemorySanitizer, UnalignedStore64) { char x[16]; - U8 y = 0; - __msan_poison(&y, 3); - __msan_poison(((char *)&y) + sizeof(y) - 2, 1); - __sanitizer_unaligned_store64(x+3, y); - EXPECT_POISONED(x[0]); - EXPECT_POISONED(x[1]); - EXPECT_POISONED(x[2]); - EXPECT_POISONED(x[3]); - EXPECT_POISONED(x[4]); - EXPECT_POISONED(x[5]); + U8 y8 = 0; + U4 origin = __LINE__; + __msan_poison(&y8, 3); + __msan_poison(((char *)&y8) + sizeof(y8) - 2, 1); + __msan_set_origin(&y8, 8, origin); + + __sanitizer_unaligned_store64(x+3, y8); + EXPECT_POISONED_O(x[0], origin); + EXPECT_POISONED_O(x[1], origin); + EXPECT_POISONED_O(x[2], origin); + EXPECT_POISONED_O(x[3], origin); + EXPECT_POISONED_O(x[4], origin); + EXPECT_POISONED_O(x[5], origin); EXPECT_NOT_POISONED(x[6]); EXPECT_NOT_POISONED(x[7]); EXPECT_NOT_POISONED(x[8]); - EXPECT_POISONED(x[9]); + EXPECT_POISONED_O(x[9], origin); EXPECT_NOT_POISONED(x[10]); - EXPECT_POISONED(x[11]); + EXPECT_POISONED_O(x[11], origin); } TEST(MemorySanitizerDr, StoreInDSOTest) {