Skip to content

Commit a848008

Browse files
authored
[lldb] Fixed UB in CPlusPlusLanguage plug-in (#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.
1 parent ba9d1c4 commit a848008

File tree

2 files changed

+8
-4
lines changed

2 files changed

+8
-4
lines changed

lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,14 +190,16 @@ static bool IsTrivialBasename(const llvm::StringRef &basename) {
190190
if (basename.size() <= idx)
191191
return false; // Empty string or "~"
192192

193-
if (!std::isalpha(basename[idx]) && basename[idx] != '_')
193+
if (!std::isalpha(static_cast<unsigned char>(basename[idx])) &&
194+
basename[idx] != '_')
194195
return false; // First character (after removing the possible '~'') isn't in
195196
// [A-Za-z_]
196197

197198
// Read all characters matching [A-Za-z_0-9]
198199
++idx;
199200
while (idx < basename.size()) {
200-
if (!std::isalnum(basename[idx]) && basename[idx] != '_')
201+
if (!std::isalnum(static_cast<unsigned char>(basename[idx])) &&
202+
basename[idx] != '_')
201203
break;
202204
++idx;
203205
}

lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,10 @@ using namespace lldb_private::formatters;
4040
static void consumeInlineNamespace(llvm::StringRef &name) {
4141
// Delete past an inline namespace, if any: __[a-zA-Z0-9_]+::
4242
auto scratch = name;
43-
if (scratch.consume_front("__") && std::isalnum(scratch[0])) {
44-
scratch = scratch.drop_while([](char c) { return std::isalnum(c); });
43+
if (scratch.consume_front("__") &&
44+
std::isalnum(static_cast<unsigned char>(scratch[0]))) {
45+
scratch = scratch.drop_while(
46+
[](char c) { return std::isalnum(static_cast<unsigned char>(c)); });
4547
if (scratch.consume_front("::")) {
4648
// Successfully consumed a namespace.
4749
name = scratch;

0 commit comments

Comments
 (0)