From c354600c6e08bad31ff7586604e32a94e9242f17 Mon Sep 17 00:00:00 2001 From: dw Date: Fri, 29 Mar 2019 11:30:19 +0000 Subject: [PATCH] Fix invalid handling of llvm MemoryBuffer in DiagnosticMain. When 'Buf' is passed to clang in addRemappedFile then clang will destroy it when the compiler instance is destroyed. So release ownership of the pointer immediately. Otherwise if the call to Parse fails then we destroy both the compiler instance (indirectly destroying the MemoryBuffer) and destroy the memory buffer again via the reference to it from 'Buf' which isn't cleared yet. This can cause a segmentation fault. --- src/sema_manager.cc | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/sema_manager.cc b/src/sema_manager.cc index deb6b153..df4510c3 100644 --- a/src/sema_manager.cc +++ b/src/sema_manager.cc @@ -300,11 +300,11 @@ std::unique_ptr BuildCompilerInstance( Session &session, std::unique_ptr CI, IntrusiveRefCntPtr FS, DiagnosticConsumer &DC, const PreambleData *preamble, const std::string &main, - std::unique_ptr &Buf) { + std::unique_ptr Buf) { if (preamble) - preamble->Preamble.OverridePreamble(*CI, FS, Buf.get()); + preamble->Preamble.OverridePreamble(*CI, FS, Buf.release()); else - CI->getPreprocessorOpts().addRemappedFile(main, Buf.get()); + CI->getPreprocessorOpts().addRemappedFile(main, Buf.release()); auto Clang = std::make_unique(session.PCH); Clang->setInvocation(std::move(CI)); @@ -485,7 +485,7 @@ void *CompletionMain(void *manager_) { continue; } auto Clang = BuildCompilerInstance(*session, std::move(CI), FS, DC, - preamble.get(), task->path, Buf); + preamble.get(), task->path, std::move(Buf)); if (!Clang) continue; @@ -493,7 +493,6 @@ void *CompletionMain(void *manager_) { Clang->setCodeCompletionConsumer(task->Consumer.release()); if (!Parse(*Clang)) continue; - Buf.release(); task->on_complete(&Clang->getCodeCompletionConsumer()); } @@ -578,12 +577,11 @@ void *DiagnosticMain(void *manager_) { std::string content = manager->wfiles->GetContent(task.path); auto Buf = llvm::MemoryBuffer::getMemBuffer(content); auto Clang = BuildCompilerInstance(*session, std::move(CI), FS, DC, - preamble.get(), task.path, Buf); + preamble.get(), task.path, std::move(Buf)); if (!Clang) continue; if (!Parse(*Clang)) continue; - Buf.release(); auto Fill = [](const DiagBase &d, Diagnostic &ret) { ret.range = lsRange{{d.range.start.line, d.range.start.column},