[clangd] Fix out-of-bounds read in packedLookup (#197021)

The `packedLookup` function doesn't work correctly with byte values over
0x7F (e.g. UTF-8 high bytes) on platforms where `char` is signed (like
x86-64). The character is treated as a negative `char`, which gets
converted to a negative `int`, which makes `I >> 2` negative, which
gives a negative index, and thus an out-of-bounds read.

The fix is to change the `int` parameter type to `unsigned char`, to
always get the value in the 0x00..0xFF range.

The issue has been discovered by the sanitizer buildbot after the
#187623 merge, which first introduced tests with non-ASCII source
content into the code-completion path.
This commit is contained in:
argothiel 2026-05-11 21:54:24 +02:00 committed by GitHub
parent 875e6226aa
commit 943a7da07a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 4 additions and 1 deletions

View file

@ -145,7 +145,8 @@ constexpr static uint8_t CharRoles[] = {
// clang-format on
};
template <typename T> static T packedLookup(const uint8_t *Data, int I) {
template <typename T>
static T packedLookup(const uint8_t *Data, unsigned char I) {
return static_cast<T>((Data[I >> 2] >> ((I & 3) * 2)) & 3);
}
CharTypeSet calculateRoles(llvm::StringRef Text,

View file

@ -305,6 +305,8 @@ TEST(FuzzyMatch, Segmentation) {
returns("+--+---+------"));
EXPECT_THAT(segment("t3h PeNgU1N oF d00m!!!!!!!!"), //
returns("+-- +-+-+-+ ++ +--- "));
EXPECT_THAT(segment("ab🙂cd"), //
returns("+-------"));
}
} // namespace