From f393e1f6b3b42e8f355e64e2fb479c571ab939bc Mon Sep 17 00:00:00 2001 From: Kadir Cetinkaya Date: Fri, 24 Feb 2023 09:52:40 +0100 Subject: [PATCH] [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 --- clang-tools-extra/clangd/Preamble.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/clang-tools-extra/clangd/Preamble.cpp b/clang-tools-extra/clangd/Preamble.cpp index e975644..f50597f 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()); -- 2.7.4