Skip to content

[lldb/Target] Fix frame recognizer list crash when registered with nullptr #749

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ def test_frame_recognizer_1(self):
target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
self.assertTrue(target, VALID_TARGET)

# Clear internal & plugins recognizers that get initialized at launch
self.runCmd("frame recognizer clear")

self.runCmd("command script import " + os.path.join(self.getSourceDir(), "recognizer.py"))

self.expect("frame recognizer list",
Expand Down
13 changes: 11 additions & 2 deletions lldb/source/Target/StackFrameRecognizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,17 @@ class StackFrameRecognizerManagerImpl {
std::string symbol, bool regexp)> const &callback) {
for (auto entry : m_recognizers) {
if (entry.is_regexp) {
callback(entry.recognizer_id, entry.recognizer->GetName(), entry.module_regexp->GetText(),
entry.symbol_regexp->GetText(), true);
std::string module_name;
std::string symbol_name;

if (entry.module_regexp)
module_name = entry.module_regexp->GetText().str();
if (entry.symbol_regexp)
symbol_name = entry.symbol_regexp->GetText().str();

callback(entry.recognizer_id, entry.recognizer->GetName(), module_name,
symbol_name, true);

} else {
callback(entry.recognizer_id, entry.recognizer->GetName(), entry.module.GetCString(),
entry.symbol.GetCString(), false);
Expand Down
2 changes: 1 addition & 1 deletion lldb/test/Shell/Recognizer/assert.test
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# UNSUPPORTED: system-windows
# UNSUPPORTED: system-windows, system-linux
# RUN: %clang_host -g -O0 %S/Inputs/assert.c -o %t.out
# RUN: %lldb -b -s %s %t.out | FileCheck %s
run
Expand Down
2 changes: 2 additions & 0 deletions lldb/unittests/Target/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ add_lldb_unittest(TargetTests
MemoryRegionInfoTest.cpp
ModuleCacheTest.cpp
PathMappingListTest.cpp
StackFrameRecognizerTest.cpp

LINK_LIBS
lldbCore
lldbHost
lldbPluginObjectFileELF
lldbPluginPlatformLinux
lldbPluginSymbolFileSymtab
lldbTarget
lldbSymbol
lldbUtility
lldbUtilityHelpers
Expand Down
83 changes: 83 additions & 0 deletions lldb/unittests/Target/StackFrameRecognizerTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
//===-- StackFrameRecognizerTest.cpp --------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Target/StackFrameRecognizer.h"
#include "Plugins/Platform/Linux/PlatformLinux.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Utility/Reproducer.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
#include "lldb/lldb-private-enumerations.h"
#include "lldb/lldb-private.h"
#include "llvm/Support/FormatVariadic.h"
#include "gtest/gtest.h"

using namespace lldb_private;
using namespace lldb_private::repro;
using namespace lldb;

namespace {
class StackFrameRecognizerTest : public ::testing::Test {
public:
void SetUp() override {
llvm::cantFail(Reproducer::Initialize(ReproducerMode::Off, llvm::None));
FileSystem::Initialize();
HostInfo::Initialize();

// Pretend Linux is the host platform.
platform_linux::PlatformLinux::Initialize();
ArchSpec arch("powerpc64-pc-linux");
Platform::SetHostPlatform(
platform_linux::PlatformLinux::CreateInstance(true, &arch));
}

void TearDown() override {
platform_linux::PlatformLinux::Terminate();
HostInfo::Terminate();
FileSystem::Terminate();
Reproducer::Terminate();
}
};

class DummyStackFrameRecognizer : public StackFrameRecognizer {
public:
std::string GetName() override { return "Dummy StackFrame Recognizer"; }
};

void RegisterDummyStackFrameRecognizer() {
static llvm::once_flag g_once_flag;

llvm::call_once(g_once_flag, []() {
RegularExpressionSP module_regex_sp = nullptr;
RegularExpressionSP symbol_regex_sp(new RegularExpression("boom"));

StackFrameRecognizerSP dummy_recognizer_sp(new DummyStackFrameRecognizer());

StackFrameRecognizerManager::AddRecognizer(
dummy_recognizer_sp, module_regex_sp, symbol_regex_sp, false);
});
}

} // namespace

TEST_F(StackFrameRecognizerTest, NullModuleRegex) {
DebuggerSP debugger_sp = Debugger::CreateInstance();
ASSERT_TRUE(debugger_sp);

RegisterDummyStackFrameRecognizer();

bool any_printed = false;
StackFrameRecognizerManager::ForEach(
[&any_printed](uint32_t recognizer_id, std::string name,
std::string function, std::string symbol,
bool regexp) { any_printed = true; });

EXPECT_TRUE(any_printed);
}