https://github.com/JDevlieghere created https://github.com/llvm/llvm-project/pull/131658
The class was taking ownership of the SBCommandPluginInterface pointer it was passed in, by wrapping it in a shared pointer. This causes a double free in the unit test when the object is destroyed and the same pointer gets freed once when the SBCommandPluginInterface goes away and then again when the shared pointer hits a zero refcount. >From 3123d7ef4146b7caaf20ede083479692f6f324c7 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere <jo...@devlieghere.com> Date: Mon, 17 Mar 2025 11:46:32 -0700 Subject: [PATCH] [lldb] Fix double free in CommandPluginInterfaceImplementation The class was taking ownership of the SBCommandPluginInterface pointer it was passed in, by wrapping it in a shared pointer. This causes a double free in the unit test when the object is destroyed and the same pointer gets freed once when the SBCommandPluginInterface goes away and then again when the shared pointer hits a zero refcount. --- lldb/source/API/SBCommandInterpreter.cpp | 2 +- .../unittests/API/SBCommandInterpreterTest.cpp | 18 +++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/lldb/source/API/SBCommandInterpreter.cpp b/lldb/source/API/SBCommandInterpreter.cpp index d153e2acdf853..de22a9dd96bd8 100644 --- a/lldb/source/API/SBCommandInterpreter.cpp +++ b/lldb/source/API/SBCommandInterpreter.cpp @@ -77,7 +77,7 @@ class CommandPluginInterfaceImplementation : public CommandObjectParsed { SBDebugger debugger_sb(m_interpreter.GetDebugger().shared_from_this()); m_backend->DoExecute(debugger_sb, command.GetArgumentVector(), sb_return); } - std::shared_ptr<lldb::SBCommandPluginInterface> m_backend; + lldb::SBCommandPluginInterface *m_backend; std::optional<std::string> m_auto_repeat_command; }; } // namespace lldb_private diff --git a/lldb/unittests/API/SBCommandInterpreterTest.cpp b/lldb/unittests/API/SBCommandInterpreterTest.cpp index 941b738e84ac8..5651e1c3dc63f 100644 --- a/lldb/unittests/API/SBCommandInterpreterTest.cpp +++ b/lldb/unittests/API/SBCommandInterpreterTest.cpp @@ -6,24 +6,28 @@ // //===----------------------------------------------------------------------===/ -#include "gtest/gtest.h" - // Use the umbrella header for -Wdocumentation. #include "lldb/API/LLDB.h" +#include "TestingSupport/SubsystemRAII.h" +#include "lldb/API/SBDebugger.h" +#include "gtest/gtest.h" #include <cstring> #include <string> using namespace lldb; +using namespace lldb_private; class SBCommandInterpreterTest : public testing::Test { protected: void SetUp() override { - SBDebugger::Initialize(); - m_dbg = SBDebugger::Create(/*source_init_files=*/false); + debugger = SBDebugger::Create(/*source_init_files=*/false); } - SBDebugger m_dbg; + void TearDown() override { SBDebugger::Destroy(debugger); } + + SubsystemRAII<lldb::SBDebugger> subsystems; + SBDebugger debugger; }; class DummyCommand : public SBCommandPluginInterface { @@ -44,7 +48,7 @@ class DummyCommand : public SBCommandPluginInterface { TEST_F(SBCommandInterpreterTest, SingleWordCommand) { // We first test a command without autorepeat DummyCommand dummy("It worked"); - SBCommandInterpreter interp = m_dbg.GetCommandInterpreter(); + SBCommandInterpreter interp = debugger.GetCommandInterpreter(); interp.AddCommand("dummy", &dummy, /*help=*/nullptr); { SBCommandReturnObject result; @@ -78,7 +82,7 @@ TEST_F(SBCommandInterpreterTest, SingleWordCommand) { } TEST_F(SBCommandInterpreterTest, MultiWordCommand) { - SBCommandInterpreter interp = m_dbg.GetCommandInterpreter(); + SBCommandInterpreter interp = debugger.GetCommandInterpreter(); auto command = interp.AddMultiwordCommand("multicommand", /*help=*/nullptr); // We first test a subcommand without autorepeat DummyCommand subcommand("It worked again"); _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits