[Lldb-commits] [lldb] a8ad2a7 - [lldb] Fix alias parsing with joined options (#190301)

via lldb-commits lldb-commits at lists.llvm.org
Sat Apr 4 07:38:34 PDT 2026


Author: Dave Lee
Date: 2026-04-04T07:38:28-07:00
New Revision: a8ad2a7d7311e9ed3b238f533085b046f9f5f31d

URL: https://github.com/llvm/llvm-project/commit/a8ad2a7d7311e9ed3b238f533085b046f9f5f31d
DIFF: https://github.com/llvm/llvm-project/commit/a8ad2a7d7311e9ed3b238f533085b046f9f5f31d.diff

LOG: [lldb] Fix alias parsing with joined options (#190301)

Fixes a crash with the following alias, which I use for printing the
contents of pointer variables:

```
command alias vp v -P1
```

At some point in the recent-ish past, parsing this alias has started
crashing lldb. The problem is code that assumes the option and its value
are separate. This assumption causes an index past the end of a vector.

This fix changes `FindArgumentIndexForOption`. The function now returns
a pair of indexes, the first index is the option, the second index is
the index of the value. In the case of joined options like `-P1`, the
two indexes are the same.

Added: 
    lldb/test/Shell/Commands/command-alias-joined-arg.test

Modified: 
    lldb/include/lldb/lldb-defines.h
    lldb/source/Interpreter/Options.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/lldb-defines.h b/lldb/include/lldb/lldb-defines.h
index 8e1029387d2da..515f7cff58d8a 100644
--- a/lldb/include/lldb/lldb-defines.h
+++ b/lldb/include/lldb/lldb-defines.h
@@ -81,6 +81,7 @@
 #define LLDB_INVALID_STOP_ID 0
 #define LLDB_INVALID_ADDRESS UINT64_MAX
 #define LLDB_INVALID_INDEX32 UINT32_MAX
+#define LLDB_INVALID_INDEX64 UINT64_MAX
 #define LLDB_INVALID_IVAR_OFFSET UINT32_MAX
 #define LLDB_INVALID_IMAGE_TOKEN UINT32_MAX
 #define LLDB_INVALID_MODULE_VERSION UINT32_MAX

diff  --git a/lldb/source/Interpreter/Options.cpp b/lldb/source/Interpreter/Options.cpp
index 283c9cc0105a1..cc9f3ebd706fd 100644
--- a/lldb/source/Interpreter/Options.cpp
+++ b/lldb/source/Interpreter/Options.cpp
@@ -21,8 +21,11 @@
 #include "lldb/Interpreter/CommandReturnObject.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Utility/AnsiTerminal.h"
+#include "lldb/Utility/OptionDefinition.h"
 #include "lldb/Utility/StreamString.h"
+#include "lldb/lldb-defines.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
 #include "llvm/Support/ErrorExtras.h"
 
 using namespace lldb;
@@ -887,18 +890,28 @@ static Args ReconstituteArgsAfterParsing(llvm::ArrayRef<char *> parsed,
   return result;
 }
 
-static size_t FindArgumentIndexForOption(const Args &args,
-                                         const Option &long_option) {
+/// Find the index of the given option in the arguments. If the option takes an
+/// argument, the second index is the index of the value in args. Otherwise, the
+/// second index is LLDB_INVALID_INDEX64.
+static std::pair<size_t, size_t>
+FindArgumentIndexForOption(const Args &args, const Option &long_option) {
   std::string short_opt = llvm::formatv("-{0}", char(long_option.val)).str();
   std::string long_opt =
-      std::string(llvm::formatv("--{0}", long_option.definition->long_option));
+      llvm::formatv("--{0}", long_option.definition->long_option).str();
   for (const auto &entry : llvm::enumerate(args)) {
-    if (entry.value().ref().starts_with(short_opt) ||
-        entry.value().ref().starts_with(long_opt))
-      return entry.index();
+    llvm::StringRef arg = entry.value().ref();
+    size_t idx = entry.index();
+    if (long_option.definition->option_has_arg == OptionParser::eNoArgument)
+      return {idx, LLDB_INVALID_INDEX64};
+    size_t val_idx;
+    if (arg == short_opt || arg.starts_with(long_opt))
+      val_idx = idx + 1;
+    else if (arg.starts_with(short_opt))
+      val_idx = idx;
+    return {idx, val_idx};
   }
 
-  return size_t(-1);
+  return {LLDB_INVALID_INDEX64, LLDB_INVALID_INDEX64};
 }
 
 static std::string BuildShortOptions(const Option *long_options) {
@@ -987,10 +1000,9 @@ llvm::Expected<Args> Options::ParseAlias(const Args &args,
 
     StreamString option_str;
     option_str.Printf("-%c", val);
-    const OptionDefinition *def = long_options[long_options_index].definition;
-    int has_arg =
-        (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
-
+    const Option &opt = long_options[long_options_index];
+    int has_arg = opt.definition ? opt.definition->option_has_arg
+                                 : OptionParser::eNoArgument;
     const char *option_arg = nullptr;
     switch (has_arg) {
     case OptionParser::eRequiredArgument:
@@ -1020,12 +1032,11 @@ llvm::Expected<Args> Options::ParseAlias(const Args &args,
     // Note: We also need to preserve any option argument values that were
     // surrounded by backticks, as we lose track of them in the
     // option_args_vector.
-    size_t idx =
-        FindArgumentIndexForOption(args_copy, long_options[long_options_index]);
+    auto [idx, val_idx] = FindArgumentIndexForOption(args_copy, opt);
     std::string option_to_insert;
     if (option_arg) {
-      if (idx != size_t(-1) && has_arg) {
-        bool arg_has_backtick = args_copy[idx + 1].GetQuoteChar() == '`';
+      if (val_idx != LLDB_INVALID_INDEX64 && val_idx < args_copy.size()) {
+        bool arg_has_backtick = args_copy[val_idx].GetQuoteChar() == '`';
         if (arg_has_backtick)
           option_to_insert = "`";
         option_to_insert += option_arg;
@@ -1039,7 +1050,7 @@ llvm::Expected<Args> Options::ParseAlias(const Args &args,
     option_arg_vector->emplace_back(std::string(option_str.GetString()),
                                     has_arg, option_to_insert);
 
-    if (idx == size_t(-1))
+    if (idx == LLDB_INVALID_INDEX64)
       continue;
 
     if (!input_line.empty()) {

diff  --git a/lldb/test/Shell/Commands/command-alias-joined-arg.test b/lldb/test/Shell/Commands/command-alias-joined-arg.test
new file mode 100644
index 0000000000000..c95672a2cc54a
--- /dev/null
+++ b/lldb/test/Shell/Commands/command-alias-joined-arg.test
@@ -0,0 +1,7 @@
+# Test that command alias with a joined argument (`-P1` in this test) is
+# properly parsed (does not crash).
+
+# RUN: %lldb < %s | FileCheck %s
+command alias vptr frame variable -P1
+help
+# CHECK: {{^ *}}vptr{{ +}}--


        


More information about the lldb-commits mailing list