https://github.com/slydiman created 
https://github.com/llvm/llvm-project/pull/158304

C++11 allows the use of Universal Character Names (UCNs) in identifiers, 
including function names.

According to the spec the behavior of std::isalpha(ch) and std::isalnum(ch) is 
undefined if the argument's value is neither representable as unsigned char nor 
equal to EOF. To use these functions safely with plain chars (or signed chars), 
the argument should first be converted to unsigned char.

>From fb325b76b2fa8ae3898fe26e0859e50ad6babbbb Mon Sep 17 00:00:00 2001
From: Dmitry Vasilyev <dvassil...@accesssoftek.com>
Date: Fri, 12 Sep 2025 18:06:29 +0400
Subject: [PATCH] [lldb] Fixed UB in CPlusPlusLanguage plug-in

C++11 allows the use of Universal Character Names (UCNs) in identifiers, 
including function names.

According to the spec the behavior of std::isalpha(ch) and std::isalnum(ch) is 
undefined if the argument's value is neither representable as unsigned char nor 
equal to EOF. To use these functions safely with plain chars (or signed chars), 
the argument should first be converted to unsigned char.
---
 .../source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp | 6 ++++--
 lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp           | 6 ++++--
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp 
b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 277de8f444828..1f7b8d48d0fc8 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -190,14 +190,16 @@ static bool IsTrivialBasename(const llvm::StringRef 
&basename) {
   if (basename.size() <= idx)
     return false; // Empty string or "~"
 
-  if (!std::isalpha(basename[idx]) && basename[idx] != '_')
+  if (!std::isalpha(static_cast<unsigned char>(basename[idx])) &&
+      basename[idx] != '_')
     return false; // First character (after removing the possible '~'') isn't 
in
                   // [A-Za-z_]
 
   // Read all characters matching [A-Za-z_0-9]
   ++idx;
   while (idx < basename.size()) {
-    if (!std::isalnum(basename[idx]) && basename[idx] != '_')
+    if (!std::isalnum(static_cast<unsigned char>(basename[idx])) &&
+        basename[idx] != '_')
       break;
     ++idx;
   }
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp 
b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
index 6053d042b29b1..141c5c9a2caf9 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
@@ -40,8 +40,10 @@ using namespace lldb_private::formatters;
 static void consumeInlineNamespace(llvm::StringRef &name) {
   // Delete past an inline namespace, if any: __[a-zA-Z0-9_]+::
   auto scratch = name;
-  if (scratch.consume_front("__") && std::isalnum(scratch[0])) {
-    scratch = scratch.drop_while([](char c) { return std::isalnum(c); });
+  if (scratch.consume_front("__") &&
+      std::isalnum(static_cast<unsigned char>(scratch[0]))) {
+    scratch = scratch.drop_while(
+        [](char c) { return std::isalnum(static_cast<unsigned char>(c)); });
     if (scratch.consume_front("::")) {
       // Successfully consumed a namespace.
       name = scratch;

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to