]> cloud.milkyroute.net Git - dolphin.git/commitdiff
versioncontrol: Prevent a use-after-free in UpdateItemStatesThread
authorMéven Car <meven@kde.org>
Sat, 23 Mar 2024 10:55:37 +0000 (11:55 +0100)
committerMéven Car <meven@kde.org>
Sun, 24 Mar 2024 10:55:54 +0000 (11:55 +0100)
UpdateItemStatesThread kept a pointer reference to m_plugin whose
lifetime was tied to VersionControlObserver parents.
On application shutdown it could happen the thread is still running when
the Observer is destroyed.

Make the plugin pointer a weak reference, allowing to stop the thread
when the plugin is gone.

BUG: 477425

src/views/versioncontrol/updateitemstatesthread.cpp
src/views/versioncontrol/updateitemstatesthread.h

index ad53517ae5fc6f036333e921e97035c3ae2cd36c..e6a0f68fa192d1de9bb156467eef0cf8b7f15ab3 100644 (file)
@@ -26,22 +26,26 @@ UpdateItemStatesThread::~UpdateItemStatesThread()
 void UpdateItemStatesThread::run()
 {
     Q_ASSERT(!m_itemStates.isEmpty());
 void UpdateItemStatesThread::run()
 {
     Q_ASSERT(!m_itemStates.isEmpty());
-    Q_ASSERT(m_plugin);
+    if (!m_plugin) {
+        return;
+    }
 
     QMutexLocker pluginLocker(m_globalPluginMutex);
     QMap<QString, QVector<VersionControlObserver::ItemState>>::iterator it = m_itemStates.begin();
 
     QMutexLocker pluginLocker(m_globalPluginMutex);
     QMap<QString, QVector<VersionControlObserver::ItemState>>::iterator it = m_itemStates.begin();
-    for (; it != m_itemStates.end(); ++it) {
+    for (; it != m_itemStates.end() && m_plugin; ++it) {
         if (m_plugin->beginRetrieval(it.key())) {
             QVector<VersionControlObserver::ItemState> &items = it.value();
             const int count = items.count();
         if (m_plugin->beginRetrieval(it.key())) {
             QVector<VersionControlObserver::ItemState> &items = it.value();
             const int count = items.count();
-            for (int i = 0; i < count; ++i) {
+            for (int i = 0; i < count && m_plugin; ++i) {
                 const KFileItem &item = items.at(i).first;
                 const KVersionControlPlugin::ItemVersion version = m_plugin->itemVersion(item);
                 items[i].second = version;
             }
         }
 
                 const KFileItem &item = items.at(i).first;
                 const KVersionControlPlugin::ItemVersion version = m_plugin->itemVersion(item);
                 items[i].second = version;
             }
         }
 
-        m_plugin->endRetrieval();
+        if (m_plugin) {
+            m_plugin->endRetrieval();
+        }
     }
 }
 
     }
 }
 
index 24f060d26652d1847378510dcd78c8c81135f76b..550436010967f7d89ab84f59495be8d1c46958b9 100644 (file)
@@ -11,6 +11,7 @@
 #include "views/versioncontrol/versioncontrolobserver.h"
 
 #include <QMutex>
 #include "views/versioncontrol/versioncontrolobserver.h"
 
 #include <QMutex>
+#include <QPointer>
 #include <QThread>
 
 /**
 #include <QThread>
 
 /**
@@ -41,7 +42,7 @@ protected:
 
 private:
     QMutex *m_globalPluginMutex; // Protects the m_plugin globally
 
 private:
     QMutex *m_globalPluginMutex; // Protects the m_plugin globally
-    KVersionControlPlugin *m_plugin;
+    QPointer<KVersionControlPlugin> m_plugin;
 
     QMap<QString, QVector<VersionControlObserver::ItemState>> m_itemStates;
 };
 
     QMap<QString, QVector<VersionControlObserver::ItemState>> m_itemStates;
 };