[Lldb-commits] [lldb] [lldb][PlatformDarwin] Disallow '+' in auto-loadable Python script names (PR #186346)

Michael Buch via lldb-commits lldb-commits at lists.llvm.org
Fri Mar 13 02:25:15 PDT 2026


https://github.com/Michael137 created https://github.com/llvm/llvm-project/pull/186346

The `ScriptInterpreterPython` will refuse to load script names with `+`. This patch makes `SanitizedScriptingModuleName` handle this by replacing it with `x`. That might seem a bit arbitrary but the way the current dSYM script loading (and the general auto-load) mechanism works is that it will look for scripts called `<lldb-module-name>.py`. So for something like `libc++.1.dylib`, we would look for `libc++.1.py`. The simplest way of working around this is to recommend renaming the script to `libcxx_1.py`. Replacing `x` with `_` like we do for other special characters would look strange in my opinion.

An alternative to the whole "replace special characters" logic is to have a MANIFEST file which advertises the script name that LLDB should load. During reading that script we could bail if we saw special characters. But since this is the path of least resistence I went with the `llvm::replace` approach for now.

>From 16515d6b08d907bf814832322fb9d456df6a5fe2 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Fri, 13 Mar 2026 09:01:54 +0000
Subject: [PATCH] [lldb][PlatformDarwin] Disallow '+' in auto-loadable Python
 script names

The `ScriptInterpreterPython` will refuse to load script names with `+`. This patch makes `SanitizedScriptingModuleName` handle this by replacing it with `x`. That might seem a bit arbitrary but the way the current dSYM script loading (and the general auto-load) mechanism works is that it will look for scripts called `<lldb-module-name>.py`. So for something like `libc++.1.dylib`, we would look for `libc++.1.py`. The simplest way of working around this is to recommend renaming the script to `libcxx_1.py`. Replacing `x` with `_` like we do for other special characters would look strange in my opinion.

An alternative to the whole "replace special characters" logic is to have a MANIFEST file which advertises the script name that LLDB should load. During reading that script we could bail if we saw special characters. But since this is the path of least resistence I went with the `llvm::replace` approach for now.
---
 .../Platform/MacOSX/PlatformDarwin.cpp        |  1 +
 .../unittests/Platform/PlatformDarwinTest.cpp | 49 +++++++++++++++++++
 2 files changed, 50 insertions(+)

diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
index 436dc5aa0f684..36c9a8a26825e 100644
--- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
+++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
@@ -102,6 +102,7 @@ class SanitizedScriptingModuleName {
     llvm::replace(m_sanitized_name, '.', '_');
     llvm::replace(m_sanitized_name, ' ', '_');
     llvm::replace(m_sanitized_name, '-', '_');
+    llvm::replace(m_sanitized_name, '+', 'x');
 
     if (script_interpreter &&
         script_interpreter->IsReservedWord(m_sanitized_name.c_str())) {
diff --git a/lldb/unittests/Platform/PlatformDarwinTest.cpp b/lldb/unittests/Platform/PlatformDarwinTest.cpp
index f5fd6660069ea..e6d1beb3a75e9 100644
--- a/lldb/unittests/Platform/PlatformDarwinTest.cpp
+++ b/lldb/unittests/Platform/PlatformDarwinTest.cpp
@@ -631,3 +631,52 @@ TEST_F(
   EXPECT_EQ(fspecs.GetFileSpecAtIndex(0).GetFilename(), "_mykeyword_1_1_1.py");
   EXPECT_TRUE(ss.Empty());
 }
+
+struct SpecialCharTestCase {
+  char special_char;
+  char replacement;
+};
+struct PlatformDarwinLocateWithSpecialCharsTestFixture
+    : public testing::WithParamInterface<SpecialCharTestCase>,
+      public PlatformDarwinLocateTest {};
+
+TEST_P(PlatformDarwinLocateWithSpecialCharsTestFixture,
+       LocateExecutableScriptingResourcesFromDSYM_SpecialCharacters) {
+  // Tests the various special characters that `ScriptInterpreterPython`
+  // disallows in module names.
+
+  auto [special_char, replacement] = GetParam();
+
+  std::string module_name = llvm::formatv("TestModule{0}.o", special_char);
+  std::string script_name = llvm::formatv("TestModule{0}.py", special_char);
+  std::string recommended_script_name =
+      llvm::formatv("TestModule{0}.py", replacement);
+
+  // Create dummy module file at <test-root>/<module-name>
+  FileSpec module_fspec(CreateFile(module_name, m_tmp_root_dir));
+  ASSERT_TRUE(module_fspec);
+
+  // Create dummy module file at
+  // <test-root>/.dSYM/Contents/Resources/DWARF/<module-name>
+  FileSpec dsym_module_fpec(CreateFile(module_name, m_tmp_dsym_dwarf_dir));
+  ASSERT_TRUE(dsym_module_fpec);
+
+  CreateFile(script_name, m_tmp_dsym_python_dir);
+
+  StreamString ss;
+  FileSpecList fspecs =
+      std::static_pointer_cast<PlatformDarwin>(m_platform_sp)
+          ->LocateExecutableScriptingResourcesFromDSYM(
+              ss, module_fspec, *m_target_sp, dsym_module_fpec);
+  EXPECT_EQ(fspecs.GetSize(), 0u);
+
+  std::string expected =
+      llvm::formatv("please rename '{0}/../Python/{1}' to '{0}/../Python/{2}'",
+                    m_tmp_dsym_dwarf_dir, script_name, recommended_script_name);
+  EXPECT_TRUE(ss.GetString().contains(expected));
+}
+
+INSTANTIATE_TEST_SUITE_P(PlatformDarwinLocateWithSpecialCharsTest,
+                         PlatformDarwinLocateWithSpecialCharsTestFixture,
+                         testing::ValuesIn(std::vector<SpecialCharTestCase>{
+                             {' ', '_'}, {'.', '_'}, {'-', '_'}, {'+', 'x'}}));



More information about the lldb-commits mailing list