diff options
author | Maurice Kalinowski <maurice.kalinowski@qt.io> | 2016-10-31 12:57:38 +0100 |
---|---|---|
committer | Maurice Kalinowski <maurice.kalinowski@qt.io> | 2016-11-08 07:32:43 +0000 |
commit | fe51dbac3d20ef9275dd1a9070f8185dc7705ad9 (patch) | |
tree | 2d568c5e90639bd0060ec70355d858af19e28070 /src/corelib/kernel/qeventdispatcher_winrt.cpp | |
parent | c972c452e2ae2f38ce957eaac1761d8dff265f9b (diff) |
winrt: Fix potential memory corruption
The timerInfo list might get accessed concurrently and cause references
to become dangling. Hence, we need to protect usages with a mutex.
According to tests/benchmark there is no impact on performance.
Task-number: QTBUG-56756
Change-Id: I4bdffccff70d2dca99f4a39defad438afe571ada
Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
Diffstat (limited to 'src/corelib/kernel/qeventdispatcher_winrt.cpp')
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_winrt.cpp | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp index d115a3db2a..4a2e2d887f 100644 --- a/src/corelib/kernel/qeventdispatcher_winrt.cpp +++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp @@ -36,6 +36,7 @@ #include <QtCore/QCoreApplication> #include <QtCore/QThread> #include <QtCore/QHash> +#include <QtCore/QMutex> #include <QtCore/qfunctions_winrt.h> #include <private/qabstracteventdispatcher_p.h> #include <private/qcoreapplication_p.h> @@ -100,6 +101,7 @@ public: private: QHash<int, QObject *> timerIdToObject; QVector<WinRTTimerInfo> timerInfos; + mutable QMutex timerInfoLock; QHash<HANDLE, int> timerHandleToId; QHash<int, HANDLE> timerIdToHandle; QHash<int, HANDLE> timerIdToCancelHandle; @@ -116,6 +118,7 @@ private: timerIdToObject.insert(id, obj); const quint64 targetTime = qt_msectime() + interval; const WinRTTimerInfo info(id, interval, type, obj, targetTime); + QMutexLocker locker(&timerInfoLock); if (id >= timerInfos.size()) timerInfos.resize(id + 1); timerInfos[id] = info; @@ -124,6 +127,7 @@ private: bool removeTimer(int id) { + QMutexLocker locker(&timerInfoLock); if (id >= timerInfos.size()) return false; @@ -247,14 +251,18 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags) if (timerId == INTERRUPT_HANDLE) break; - WinRTTimerInfo &info = d->timerInfos[timerId]; - Q_ASSERT(info.timerId != INVALID_TIMER_ID); + { + QMutexLocker locker(&d->timerInfoLock); - QCoreApplication::postEvent(this, new QTimerEvent(timerId)); + WinRTTimerInfo &info = d->timerInfos[timerId]; + Q_ASSERT(info.timerId != INVALID_TIMER_ID); - // Update timer's targetTime - const quint64 targetTime = qt_msectime() + info.interval; - info.targetTime = targetTime; + QCoreApplication::postEvent(this, new QTimerEvent(timerId)); + + // Update timer's targetTime + const quint64 targetTime = qt_msectime() + info.interval; + info.targetTime = targetTime; + } waitResult = WaitForMultipleObjectsEx(timerHandles.count(), timerHandles.constData(), FALSE, 0, TRUE); } emit awake(); @@ -421,6 +429,7 @@ QList<QAbstractEventDispatcher::TimerInfo> QEventDispatcherWinRT::registeredTime } Q_D(const QEventDispatcherWinRT); + QMutexLocker locker(&d->timerInfoLock); QList<TimerInfo> timerInfos; foreach (const WinRTTimerInfo &info, d->timerInfos) { if (info.object == object && info.timerId != INVALID_TIMER_ID) @@ -452,6 +461,7 @@ int QEventDispatcherWinRT::remainingTime(int timerId) } Q_D(QEventDispatcherWinRT); + QMutexLocker locker(&d->timerInfoLock); const WinRTTimerInfo timerInfo = d->timerInfos.at(timerId); if (timerInfo.timerId == INVALID_TIMER_ID) { #ifndef QT_NO_DEBUG @@ -500,6 +510,9 @@ bool QEventDispatcherWinRT::event(QEvent *e) case QEvent::Timer: { QTimerEvent *timerEvent = static_cast<QTimerEvent *>(e); const int id = timerEvent->timerId(); + + QMutexLocker locker(&d->timerInfoLock); + Q_ASSERT(id < d->timerInfos.size()); WinRTTimerInfo &info = d->timerInfos[id]; Q_ASSERT(info.timerId != INVALID_TIMER_ID); @@ -508,9 +521,13 @@ bool QEventDispatcherWinRT::event(QEvent *e) break; info.inEvent = true; + locker.unlock(); + QTimerEvent te(id); QCoreApplication::sendEvent(d->timerIdToObject.value(id), &te); + locker.relock(); + // The timer might have been removed in the meanwhile if (id >= d->timerInfos.size()) break; |