commit b9fa9885509451ebda813b07fde46f410b1bf15a
parent 0eb0446119d0c5bf570ca4534c227e0a318e8f30
Author: cfillion <cfillion@users.noreply.github.com>
Date: Sun, 5 Feb 2017 23:58:55 -0500
download: fix use after free of m_mutex (same as 1ae44ee634057a11dfa1a33cc9597b45b41b8667)
Diffstat:
2 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/src/download.cpp b/src/download.cpp
@@ -328,11 +328,6 @@ void DownloadQueue::abort()
m_onAbort();
}
-DownloadNotifier::DownloadNotifier() : m_active(0)
-{
- assert(!s_instance);
-}
-
DownloadNotifier *DownloadNotifier::get()
{
if(!s_instance)
@@ -362,20 +357,24 @@ void DownloadNotifier::notify(const Notification ¬if)
void DownloadNotifier::tick()
{
DownloadNotifier *instance = DownloadNotifier::get();
+ instance->processQueue();
- WDL_MutexLock lock(&instance->m_mutex);
-
- while(!instance->m_queue.empty()) {
- const Notification notif = instance->m_queue.front();
- instance->m_queue.pop();
-
- notif.first->setState(notif.second);
- // `this` can be destroyed here
- }
-
+ // doing this in stop() would cause a use after free of m_mutex in processQueue
if(!instance->m_active) {
plugin_register("-timer", (void *)tick);
- s_instance = nullptr;
+
delete s_instance;
+ s_instance = nullptr;
+ }
+}
+
+void DownloadNotifier::processQueue()
+{
+ WDL_MutexLock lock(&m_mutex);
+
+ while(!m_queue.empty()) {
+ const Notification ¬if = m_queue.front();
+ notif.first->setState(notif.second);
+ m_queue.pop();
}
}
diff --git a/src/download.hpp b/src/download.hpp
@@ -156,8 +156,6 @@ class DownloadNotifier {
public:
static DownloadNotifier *get();
- DownloadNotifier();
-
void start();
void stop();
@@ -167,6 +165,10 @@ private:
static DownloadNotifier *s_instance;
static void tick();
+ DownloadNotifier() : m_active(0) {}
+ ~DownloadNotifier() = default;
+ void processQueue();
+
WDL_Mutex m_mutex;
size_t m_active;
std::queue<Notification> m_queue;