[LLDB] Fix Timer MSAN Use After Destroy in Fuzz Tests (#186133)

0e314ef4a6 updated the fuzz tests to
ensure that they call SBDebugger::Terminate() on shutdown. However, this
ended up causing msan failures. Initializing the static variable on the
first fuzz test ends up causing use after destroys as timers are stored
in a thread_local static variable in LLDB. This ends up getting
destroyed earlier (by virtue of being thread_local) than the
SBDebuggerContextManager.

So we move initialization back into LLVMFuzzerInitialize to ensure that
timers are initialized before SBDebuggerContextManager is (which will
ensure they are destroyed later) and make SBDebuggerContextManager
thread_local to ensure the correct destruction order.

I couldn't find any issues calling SBDebugger::Terminate() multiple
times, but that doesn't seem right and it's trivial to make the context
manager ref counting.

This does make the code a bit messier and harder to understand, but
seems like the simplest way to get everything working given there
doesn't seem to be any LLVMFuzzerCleanup method or anything.
This commit is contained in:
Aiden Grossman
2026-03-12 09:29:38 -07:00
committed by GitHub
parent 964a3ad051
commit b34c4284e9
3 changed files with 23 additions and 5 deletions

View File

@@ -19,8 +19,14 @@
using namespace lldb;
using namespace lldb_fuzzer;
extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
SBDebugger::Initialize();
return 0;
}
extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
static SBDebuggerContextManager ctx_manager = SBDebuggerContextManager();
static thread_local SBDebuggerContextManager ctx_manager =
SBDebuggerContextManager();
// Convert the data into a null-terminated string
std::string str((char *)data, size);

View File

@@ -16,8 +16,14 @@ using namespace lldb;
using namespace lldb_fuzzer;
using namespace llvm;
extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
SBDebugger::Initialize();
return 0;
}
extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
static SBDebuggerContextManager ctx_manager = SBDebuggerContextManager();
static thread_local SBDebuggerContextManager ctx_manager =
SBDebuggerContextManager();
std::unique_ptr<TempFile> file = TempFile::Create(data, size);
if (!file)

View File

@@ -13,10 +13,16 @@ using namespace lldb;
namespace lldb_fuzzer {
class SBDebuggerContextManager {
public:
SBDebuggerContextManager() { SBDebugger::Initialize(); }
inline static int instance_count;
~SBDebuggerContextManager() { SBDebugger::Terminate(); }
public:
SBDebuggerContextManager() { ++instance_count; }
~SBDebuggerContextManager() {
--instance_count;
if (instance_count == 0)
SBDebugger::Terminate();
}
};
} // namespace lldb_fuzzer