Unpoison stack frame ptrs from libunwind for msan

Turned out that in msan builds, stack frame pointers explicitly returned
by unw_backtrace() in Common/StackTrace.cpp were unpoisened, but stack
frame pointers returned from the same function under the
STD_EXCEPTION_HAS_STACK_TRACE define in std::exception (see (*)) were
not. I tried unpoisoning directly in libcxx. Since this didn't work,
this PR unpoisons where get_stack_trace_frames() is called.

I don't know why this issue never occurred in CI but it fixes #48385 for
me (where msan complains about reads of uninitialized data when query
cache squashes and compresses chunks produced from SELECT last_error_trace
FROM system.errors).

Fixes: #48385

(*) https://github.com/ClickHouse/llvm-project/pull/7/files#diff-8c81d74ef72967be2fa27a31275000aa18532a583490f9673c62d7b981a5b39c
This commit is contained in:
Robert Schulze 2023-04-28 17:00:58 +00:00
parent ed97e46d41
commit 7609832606
No known key found for this signature in database
GPG Key ID: 26703B55FB13728A

View File

@ -15,6 +15,7 @@
#include <Common/formatReadable.h>
#include <Common/filesystemHelpers.h>
#include <Common/ErrorCodes.h>
#include <Common/MemorySanitizer.h>
#include <Common/SensitiveDataMasker.h>
#include <Common/LockMemoryExceptionInThread.h>
#include <filesystem>
@ -96,7 +97,10 @@ Exception::Exception(CreateFromPocoTag, const Poco::Exception & exc)
: Poco::Exception(exc.displayText(), ErrorCodes::POCO_EXCEPTION)
{
#ifdef STD_EXCEPTION_HAS_STACK_TRACE
set_stack_trace(exc.get_stack_trace_frames(), exc.get_stack_trace_size());
auto stack_trace_frames = exc.get_stack_trace_frames();
auto stack_trace_size = exc.get_stack_trace_size();
__msan_unpoison(stack_trace_frames, stack_trace_size * sizeof(stack_trace_frames[0]));
set_stack_trace(stack_trace_frames, stack_trace_size);
#endif
}
@ -104,7 +108,10 @@ Exception::Exception(CreateFromSTDTag, const std::exception & exc)
: Poco::Exception(demangle(typeid(exc).name()) + ": " + String(exc.what()), ErrorCodes::STD_EXCEPTION)
{
#ifdef STD_EXCEPTION_HAS_STACK_TRACE
set_stack_trace(exc.get_stack_trace_frames(), exc.get_stack_trace_size());
auto stack_trace_frames = exc.get_stack_trace_frames();
auto stack_trace_size = exc.get_stack_trace_size();
__msan_unpoison(stack_trace_frames, stack_trace_size * sizeof(stack_trace_frames[0]));
set_stack_trace(stack_trace_frames, stack_trace_size);
#endif
}
@ -112,7 +119,10 @@ Exception::Exception(CreateFromSTDTag, const std::exception & exc)
std::string getExceptionStackTraceString(const std::exception & e)
{
#ifdef STD_EXCEPTION_HAS_STACK_TRACE
return StackTrace::toString(e.get_stack_trace_frames(), 0, e.get_stack_trace_size());
auto stack_trace_frames = e.get_stack_trace_frames();
auto stack_trace_size = e.get_stack_trace_size();
__msan_unpoison(stack_trace_frames, stack_trace_size * sizeof(stack_trace_frames[0]));
return StackTrace::toString(stack_trace_frames, 0, stack_trace_size);
#else
if (const auto * db_exception = dynamic_cast<const Exception *>(&e))
return db_exception->getStackTraceString();
@ -140,7 +150,10 @@ std::string getExceptionStackTraceString(std::exception_ptr e)
std::string Exception::getStackTraceString() const
{
#ifdef STD_EXCEPTION_HAS_STACK_TRACE
return StackTrace::toString(get_stack_trace_frames(), 0, get_stack_trace_size());
auto stack_trace_frames = e.get_stack_trace_frames();
auto stack_trace_size = e.get_stack_trace_size();
__msan_unpoison(stack_trace_frames, stack_trace_size * sizeof(stack_trace_frames[0]));
return StackTrace::toString(stack_trace_frames, 0, stack_trace_size);
#else
return trace.toString();
#endif
@ -156,6 +169,7 @@ Exception::FramePointers Exception::getStackFramePointers() const
{
frame_pointers[i] = get_stack_trace_frames()[i];
}
__msan_unpoison(frame_pointers.data(), frame_pointers.size() * sizeof(frame_pointers[0]));
}
#else
{