From aeb626920c8050176d9d2dad9b2bae113e9bc419 Mon Sep 17 00:00:00 2001 From: Sam McCall Date: Mon, 19 Feb 2018 09:31:26 +0000 Subject: [PATCH] [clangd] Fix use-after-free in SymbolYAML: strings are owned by yaml::Input! Summary: There are a few implementation options here - alternatives are either both awkward and inefficient, or really inefficient. This is at least potentially a hot path when used as a reducer for common symbols. (Also fix an unused-var that sneaked in) Reviewers: ioeric Subscribers: klimek, ilya-biryukov, jkorous-apple, cfe-commits Differential Revision: https://reviews.llvm.org/D43381 llvm-svn: 325476 --- clang-tools-extra/clangd/XRefs.cpp | 3 +-- .../global-symbol-builder/GlobalSymbolBuilderMain.cpp | 5 +++-- clang-tools-extra/clangd/index/SymbolYAML.cpp | 9 ++++----- clang-tools-extra/clangd/index/SymbolYAML.h | 8 +++++--- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp index b6e5192184c0..b867a55dd84b 100644 --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -360,9 +360,8 @@ static std::string NamedDeclQualifiedName(const NamedDecl *ND, static llvm::Optional getScopeName(const Decl *D) { const DeclContext *DC = D->getDeclContext(); - if (const TranslationUnitDecl *TUD = dyn_cast(DC)) + if (isa(DC)) return std::string("global namespace"); - if (const TypeDecl *TD = dyn_cast(DC)) return TypeDeclToString(TD); else if (const NamespaceDecl *ND = dyn_cast(DC)) diff --git a/clang-tools-extra/clangd/global-symbol-builder/GlobalSymbolBuilderMain.cpp b/clang-tools-extra/clangd/global-symbol-builder/GlobalSymbolBuilderMain.cpp index a6c740aecbfc..b4f7f0baeb80 100644 --- a/clang-tools-extra/clangd/global-symbol-builder/GlobalSymbolBuilderMain.cpp +++ b/clang-tools-extra/clangd/global-symbol-builder/GlobalSymbolBuilderMain.cpp @@ -20,7 +20,6 @@ #include "index/SymbolYAML.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendActions.h" -#include "clang/Frontend/CompilerInstance.h" #include "clang/Index/IndexDataConsumer.h" #include "clang/Index/IndexingAction.h" #include "clang/Tooling/CommonOptionsParser.h" @@ -31,6 +30,7 @@ #include "llvm/Support/Path.h" #include "llvm/Support/Signals.h" #include "llvm/Support/ThreadPool.h" +#include "llvm/Support/YAMLTraits.h" using namespace llvm; using namespace clang::tooling; @@ -117,7 +117,8 @@ SymbolSlab mergeSymbols(tooling::ToolResults *Results) { Symbol::Details Scratch; Results->forEachResult([&](llvm::StringRef Key, llvm::StringRef Value) { Arena.Reset(); - auto Sym = clang::clangd::SymbolFromYAML(Value, Arena); + llvm::yaml::Input Yin(Value, &Arena); + auto Sym = clang::clangd::SymbolFromYAML(Yin, Arena); clang::clangd::SymbolID ID; Key >> ID; if (const auto *Existing = UniqueSymbols.find(ID)) diff --git a/clang-tools-extra/clangd/index/SymbolYAML.cpp b/clang-tools-extra/clangd/index/SymbolYAML.cpp index c96e9cb57d2a..379cb334d6b0 100644 --- a/clang-tools-extra/clangd/index/SymbolYAML.cpp +++ b/clang-tools-extra/clangd/index/SymbolYAML.cpp @@ -12,7 +12,6 @@ #include "llvm/ADT/Optional.h" #include "llvm/Support/Errc.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/YAMLTraits.h" #include "llvm/Support/raw_ostream.h" LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(clang::clangd::Symbol) @@ -176,11 +175,11 @@ SymbolSlab SymbolsFromYAML(llvm::StringRef YAMLContent) { return std::move(Syms).build(); } -Symbol SymbolFromYAML(llvm::StringRef YAMLContent, - llvm::BumpPtrAllocator &Arena) { - llvm::yaml::Input Yin(YAMLContent, &Arena); +Symbol SymbolFromYAML(llvm::yaml::Input &Input, llvm::BumpPtrAllocator &Arena) { + // We could grab Arena out of Input, but it'd be a huge hazard for callers. + assert(Input.getContext() == &Arena); Symbol S; - Yin >> S; + Input >> S; return S; } diff --git a/clang-tools-extra/clangd/index/SymbolYAML.h b/clang-tools-extra/clangd/index/SymbolYAML.h index d06d3f29a890..ed17cbf608b5 100644 --- a/clang-tools-extra/clangd/index/SymbolYAML.h +++ b/clang-tools-extra/clangd/index/SymbolYAML.h @@ -20,6 +20,7 @@ #include "Index.h" #include "llvm/Support/Error.h" +#include "llvm/Support/YAMLTraits.h" #include "llvm/Support/raw_ostream.h" namespace clang { @@ -28,9 +29,10 @@ namespace clangd { // Read symbols from a YAML-format string. SymbolSlab SymbolsFromYAML(llvm::StringRef YAMLContent); -// Read one symbol from a YAML-format string, backed by the arena. -Symbol SymbolFromYAML(llvm::StringRef YAMLContent, - llvm::BumpPtrAllocator &Arena); +// Read one symbol from a YAML-stream. +// The arena must be the Input's context! (i.e. yaml::Input Input(Text, &Arena)) +// The returned symbol is backed by both Input and Arena. +Symbol SymbolFromYAML(llvm::yaml::Input &Input, llvm::BumpPtrAllocator &Arena); // Convert a single symbol to YAML-format string. // The YAML result is safe to concatenate.