I have previously been investigating a specific sanitizer-related test case introduced by this patch: https://reviews.llvm.org/D57731. On RHEL 7, we see an MSan error coming from compiler-rt/test/sanitizer-common/TestCases/Posix/getpw_getgr.cc.
The particular error I am seeing looks like the following (with MemorySanitizer origin tracking enabled):
Uninitialized bytes in __interceptor_getgrnam at offset 4 inside [0x3010000002b8, 5)
==232690==WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x23db41b8 in void test<group, group* ()(char const), char const*>(group* ()(char const), char const*) /home/aamyk/llvm/dev/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Posix/getpw_getgr.cc:57:15
#1 0x23db2688 in main /home/aamyk/llvm/dev/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Posix/getpw_getgr.cc:75:3
#2 0x3fffb7a4497c in generic_start_main.isra.0 (/lib64/libc.so.6+0x2497c)
Uninitialized value was created by a heap allocation
#0 0x23db0030 in operator new(unsigned long) /home/aamyk/llvm/dev/llvm-project/compiler-rt/lib/msan/msan_new_delete.cc:45
#1 0x3fffb7ec8d60 in std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator const&) (/lib64/libstdc++.so.6+0x118d60)
#2 0x3fffb7ec9110 in std::string::_M_mutate(unsigned long, unsigned long, unsigned long) (/lib64/libstdc++.so.6+0x119110)
#3 0x3fffb7ec9d58 in std::string::_M_replace_safe(unsigned long, unsigned long, char const*, unsigned long) (/lib64/libstdc++.so.6+0x119d58)
#4 0x3fffb7ec9e4c in std::string::assign(char const*, unsigned long) (/lib64/libstdc++.so.6+0x119e4c)
#5 0x3fffb7eca0f8 in std::string::operator=(char const*) (/lib64/libstdc++.so.6+0x11a0f8)
#6 0x23db1fc0 in Check(group const*) /home/aamyk/llvm/dev/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Posix/getpw_getgr.cc:52:15
#7 0x23db3e8c in void test<group, group* ()(unsigned int), int>(group (*)(unsigned int), int) /home/aamyk/llvm/dev/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Posix/getpw_getgr.cc:58:3
#8 0x23db25fc in main /home/aamyk/llvm/dev/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Posix/getpw_getgr.cc:74:3
#9 0x3fffb7a4497c in generic_start_main.isra.0 (/lib64/libc.so.6+0x2497c)
#10 0x3fffb7a44b70 in __libc_start_main (/lib64/libc.so.6+0x24b70)
SUMMARY: MemorySanitizer: use-of-uninitialized-value /home/aamyk/llvm/dev/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Posix/getpw_getgr.cc:57:15 in void test<group, group* ()(char const), char const*>(group* ()(char const), char const*)
If I follow the test case correctly, there is a global string declared initially, then it gets assigned to in line 52 (coming from a call on line 72). The problematic lines of the test case seem to be lines 73 and 92, when the std::string’s c_str() is passed into the function, getgrnam(const char *).
What I found interesting is that on RHEL 7, it seems we are not using the newer C++11 ABI by default (in other words, the macro _GLIBCXX_USE_CXX11_ABI is set to 0). However, on another system where the C++11 ABI is used (_GLIBCXX_USE_CXX11_ABI macro is set to 1 by default), we do not see this MemorySanitizer error. In order to replicate the initial failure I saw previously on RHEL, I set _GLIBCXX_USE_CXX11_ABI=0 on the machine where the C++11 ABI was used and saw the failure.
Does this sound like an issue related to the different behaviour of std::string between the old and new ABIs? Or perhaps is this an issue related to _GLIBCXX_USE_CXX11_ABI at all? It would be interesting to determine if:
- Could this be a false positive?
- Should MSan not be used on applications using the “old string”?
- Maybe MSan is discovering something about the old string that we should care about?
I could very well be misunderstanding something or overseeing an important detail about sanitizers, so if anyone could share some insight into this situation or is wanting to do more investigation on this, it would be greatly appreciated.