[clang-tools-extra] f393e1f - [clangd] Fix UB in scanPreamble

Kadir Cetinkaya via cfe-commits cfe-commits at lists.llvm.org
Fri Feb 24 01:44:26 PST 2023


Author: Kadir Cetinkaya
Date: 2023-02-24T10:43:12+01:00
New Revision: f393e1f6b3b42e8f355e64e2fb479c571ab939bc

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

LOG: [clangd] Fix UB in scanPreamble

getMemBufferCopy triggers an UB when it receives a default constructed
StringRef. Make sure that we're always passing the null-terminated string
created in ParseInputs throughout the scanPreamble.

Differential Revision: https://reviews.llvm.org/D144708

Added: 
    

Modified: 
    clang-tools-extra/clangd/Preamble.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clangd/Preamble.cpp b/clang-tools-extra/clangd/Preamble.cpp
index e97564497954..f50597f9ad20 100644
--- a/clang-tools-extra/clangd/Preamble.cpp
+++ b/clang-tools-extra/clangd/Preamble.cpp
@@ -332,6 +332,8 @@ scanPreamble(llvm::StringRef Contents, const tooling::CompileCommand &Cmd) {
   EmptyFS FS;
   // Build and run Preprocessor over the preamble.
   ParseInputs PI;
+  // Memory buffers below expect null-terminated && non-null strings. So make
+  // sure to always use PI.Contents!
   PI.Contents = Contents.str();
   PI.TFS = &FS;
   PI.CompileCommand = Cmd;
@@ -345,8 +347,8 @@ scanPreamble(llvm::StringRef Contents, const tooling::CompileCommand &Cmd) {
   // twice. However, it's important to precisely follow the preamble bounds used
   // elsewhere.
   auto Bounds = ComputePreambleBounds(*CI->getLangOpts(), *ContentsBuffer, 0);
-  auto PreambleContents =
-      llvm::MemoryBuffer::getMemBufferCopy(Contents.substr(0, Bounds.Size));
+  auto PreambleContents = llvm::MemoryBuffer::getMemBufferCopy(
+      llvm::StringRef(PI.Contents).take_front(Bounds.Size));
   auto Clang = prepareCompilerInstance(
       std::move(CI), nullptr, std::move(PreambleContents),
       // Provide an empty FS to prevent preprocessor from performing IO. This
@@ -739,9 +741,8 @@ PreamblePatch PreamblePatch::create(llvm::StringRef FileName,
   //   whole preamble, which is terribly slow.
   // - If scanning for Modified fails, cannot figure out newly added ones so
   //   there's nothing to do but generate an empty patch.
-  auto BaselineScan = scanPreamble(
-      // Contents needs to be null-terminated.
-      Baseline.Preamble.getContents(), Modified.CompileCommand);
+  auto BaselineScan =
+      scanPreamble(Baseline.Preamble.getContents(), Modified.CompileCommand);
   if (!BaselineScan) {
     elog("Failed to scan baseline of {0}: {1}", FileName,
          BaselineScan.takeError());


        


More information about the cfe-commits mailing list