[PATCH] D159363: [clangd] SIGSEGV at clangd: DiagnosticConsumer Is Used After Free

Ivan Murashko via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 1 08:48:58 PDT 2023


ivanmurashko created this revision.
ivanmurashko added reviewers: kadircet, sammccall.
ivanmurashko added projects: clang, clang-tools-extra.
Herald added a subscriber: arphaman.
Herald added a project: All.
ivanmurashko requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.

This is a follow-up patch for D148088 <https://reviews.llvm.org/D148088>. The dynamic symbol index (`FileIndex::updatePreamble`) may run in a separate thread, and the `DiagnosticConsumer` that is set up in `buildPreamble` might go out of scope before it is used. This could result in a SIGSEGV when attempting to call any method of the `DiagnosticConsumer` class.

The function `buildPreamble` sets up the `DiagnosticConsumer` as follows:

  ... buildPreamble(...) {
  ...
    StoreDiags PreambleDiagnostics;
    ...
    llvm::IntrusiveRefCntPtr<DiagnosticsEngine> PreambleDiagsEngine =
      CompilerInstance::createDiagnostics(&CI.getDiagnosticOpts(),
                                          &PreambleDiagnostics,
                                          /*ShouldOwnClient=*/false);
    ...
    // The call might use the diagnostic consumer in a separate thread
    PreambleCallback(...)
    ...
  }

`PreambleDiagnostics` might be out of scope for `buildPreamble` function when we call it inside `PreambleCallback` in a separate thread.

The Fix
The fix involves replacing the client (DiagnosticConsumer) with an `IgnoringDiagConsumer` instance, which will print messages to the clangd log.

Alternatively, we can replace `PreambleDiagnostics` with an object that is owned by `DiagnosticsEngine`.

Note
There is no corresponding LIT/GTest for this issue, since there is a specific race condition that is difficult to reproduce within a test framework.

Test Plan:

  ninja check-clangd


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D159363

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


Index: clang-tools-extra/clangd/Preamble.cpp
===================================================================
--- clang-tools-extra/clangd/Preamble.cpp
+++ clang-tools-extra/clangd/Preamble.cpp
@@ -706,6 +706,11 @@
       // While extending the life of FileMgr and VFS, StatCache should also be
       // extended.
       Ctx->setStatCache(Result->StatCache);
+      // We have to setup DiagnosticConsumer that will be alife
+      // while preamble callback is executed
+      Ctx->getASTContext().getDiagnostics().setClient(new IgnoringDiagConsumer,
+                                                      true);
+
       PreambleCallback(std::move(*Ctx), Result->Pragmas);
     }
     return Result;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D159363.555396.patch
Type: text/x-patch
Size: 705 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20230901/d35bd4cb/attachment-0001.bin>


More information about the cfe-commits mailing list