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>bb10
parent
c972c452e2
commit
fe51dbac3d
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue