From 3004ebc0af36b165b8cfc7508752111c6a30b685 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Tue, 24 Sep 2024 14:23:53 +0200 Subject: [PATCH] LanguageClient: fix crash in call and type hierarchy The response to a request sent by Call or TypeHierarchy was still handled by deleted Hierarchy instances. This happens when a second request was sent before the first was handled. Make sure to cancel a potentially running request when destructing a hierarchy in order to prevent accessing the deleted instance. Change-Id: Icd810f7a6e9eb090b28f13cb1a3254f75a27cdbb Reviewed-by: Christian Kandeler --- .../languageclient/callandtypehierarchy.cpp | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/plugins/languageclient/callandtypehierarchy.cpp b/src/plugins/languageclient/callandtypehierarchy.cpp index 4b8f7117132..71a9558f34e 100644 --- a/src/plugins/languageclient/callandtypehierarchy.cpp +++ b/src/plugins/languageclient/callandtypehierarchy.cpp @@ -287,6 +287,12 @@ public: theWidget, [this](const QModelIndex &index) { onItemDoubleClicked(index); }); } + ~HierarchyWidgetHelper() + { + if (m_runningRequest && m_runningRequest->first) + m_runningRequest->first->cancelRequest(m_runningRequest->second); + } + void updateHierarchyAtCursorPosition() { m_model.clear(); @@ -315,6 +321,17 @@ protected: item->forChildrenAtLevel(1, [&](const TreeItem *child) { m_view->expand(child->index()); }); } + void send(Client *client, const JsonRpcMessage &request, const MessageId &requestId) + { + m_runningRequest = std::make_pair(QPointer(client), requestId); + client->sendMessage(request); + } + + void resetRunningRequest() + { + m_runningRequest.reset(); + } + private: virtual void sendRequest(Client *client, const TextDocumentPositionParams ¶ms, const Core::IDocument *document) = 0; @@ -334,6 +351,7 @@ private: AnnotatedItemDelegate m_delegate; NavigationTreeView * const m_view; + std::optional, MessageId>> m_runningRequest; TreeModel m_model; }; @@ -358,12 +376,13 @@ private: const PrepareCallHierarchyRequest::Response &response) { handlePrepareResponse(client, response); }); - client->sendMessage(request); + send(client, request, request.id()); } void handlePrepareResponse(Client *client, const PrepareCallHierarchyRequest::Response &response) { + resetRunningRequest(); if (!client) return; const std::optional error = response.error(); @@ -401,12 +420,13 @@ private: const PrepareTypeHierarchyRequest::Response &response) { handlePrepareResponse(client, response); }); - client->sendMessage(request); + send(client, request, request.id()); } void handlePrepareResponse(Client *client, const PrepareTypeHierarchyRequest::Response &response) { + resetRunningRequest(); if (!client) return; const std::optional error = response.error();