Index: test/msan/dlerror.cc =================================================================== --- test/msan/dlerror.cc +++ test/msan/dlerror.cc @@ -1,9 +1,30 @@ // RUN: %clangxx_msan -O0 %s -o %t && %run %t // -// AArch64, MIPS64 shows fails with uninitialized bytes in __interceptor_strcmp from -// dlfcn/dlerror.c:107 (glibc). +// Everything but x86 shows fails with uninitialized bytes in __interceptor_strcmp from +// dlfcn/dlerror.c:107 (glibc). Here's a summary of the problem: +// +// 1. dlopen calls to ld.so +// 2. ld.so fails to load the library +// 3. ld.so malloc()s a buffer for the error message. malloc is external +// to ld.so, so the usual symbol resolution happens, and our interceptor +// is called. The memory is poisoned. +// 4. ld.so memcpy's the error string to the buffer. ld.so includes its +// own copy of memcpy (for bootstraping), which doesn't go through +// the usual dynamic binding. Hence the buffer remains poisoned, even +// though it was just initialized. +// 5. dlerror is called. dlerror implementation is wholly in libdl.so. +// 6. dlerror calls strcmp on the above buffer. Since libdl.so doesn't +// have bootstrapping issues, this uses normal dynamic binding - calling +// msan's interceptor. +// 7. __intercept_strcmp notices the (wrongly) poisoned buffer, and explodes. +// +// On x86, gcc converts the strcmp call to a repz cmpsb instruction, avoiding +// the call to our interceptor, and the test passes. Other architectures +// (and x86 if glibc were to be compiled with -O0) are out of luck. +// // XFAIL: aarch64 // XFAIL: mips64 +// XFAIL: powerpc64, powerpc64le #include #include