QWindowsFontDatabase: fix a data race

QRawFont::loadFromData can be called from any thread. It calls into
QPlatformFontDatabase::fontEngine. The code path may end up creating a
UniqueFontData and storing it a QWindowsFontDatabase member (a QMap).

Two threads calling loadFromData (on different QRawFont objects)
will therefore race on the mutation of the map.

Add the missing mutex protection.

Change-Id: Ib38c2b3539679c820d997a6548e4b397cbc2bb73
Pick-to: 6.5 6.2
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
(cherry picked from commit a1b55b1360acff00f9932d99ab48f4614754e3b8)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Giuseppe D'Angelo 2023-09-13 12:44:41 +02:00 committed by Qt Cherry-pick Bot
parent 7a705e9c60
commit 018d273557
2 changed files with 10 additions and 1 deletions

View File

@ -32,6 +32,8 @@
# include "qwindowsfontenginedirectwrite_p.h" # include "qwindowsfontenginedirectwrite_p.h"
#endif #endif
#include <mutex>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals; using namespace Qt::StringLiterals;
@ -847,7 +849,10 @@ QT_WARNING_POP
UniqueFontData uniqueData; UniqueFontData uniqueData;
uniqueData.handle = fontHandle; uniqueData.handle = fontHandle;
uniqueData.refCount.ref(); uniqueData.refCount.ref();
m_uniqueFontData[uniqueFamilyName] = uniqueData; {
const std::scoped_lock lock(m_uniqueFontDataMutex);
m_uniqueFontData[uniqueFamilyName] = uniqueData;
}
} }
} else { } else {
RemoveFontMemResourceEx(fontHandle); RemoveFontMemResourceEx(fontHandle);
@ -1107,6 +1112,7 @@ bool QWindowsFontDatabase::fontsAlwaysScalable() const
void QWindowsFontDatabase::derefUniqueFont(const QString &uniqueFont) void QWindowsFontDatabase::derefUniqueFont(const QString &uniqueFont)
{ {
const std::scoped_lock lock(m_uniqueFontDataMutex);
const auto it = m_uniqueFontData.find(uniqueFont); const auto it = m_uniqueFontData.find(uniqueFont);
if (it != m_uniqueFontData.end()) { if (it != m_uniqueFontData.end()) {
if (!it->refCount.deref()) { if (!it->refCount.deref()) {
@ -1118,6 +1124,7 @@ void QWindowsFontDatabase::derefUniqueFont(const QString &uniqueFont)
void QWindowsFontDatabase::refUniqueFont(const QString &uniqueFont) void QWindowsFontDatabase::refUniqueFont(const QString &uniqueFont)
{ {
const std::scoped_lock lock(m_uniqueFontDataMutex);
const auto it = m_uniqueFontData.find(uniqueFont); const auto it = m_uniqueFontData.find(uniqueFont);
if (it != m_uniqueFontData.end()) if (it != m_uniqueFontData.end())
it->refCount.ref(); it->refCount.ref();

View File

@ -21,6 +21,7 @@
#include <QtCore/QSharedPointer> #include <QtCore/QSharedPointer>
#include <QtCore/QLoggingCategory> #include <QtCore/QLoggingCategory>
#include <QtCore/qhashfunctions.h> #include <QtCore/qhashfunctions.h>
#include <QtCore/qmutex.h>
#include <QtCore/qt_windows.h> #include <QtCore/qt_windows.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -89,6 +90,7 @@ private:
QAtomicInt refCount; QAtomicInt refCount;
}; };
QMutex m_uniqueFontDataMutex; // protects m_uniqueFontData
QMap<QString, UniqueFontData> m_uniqueFontData; QMap<QString, UniqueFontData> m_uniqueFontData;
static unsigned m_fontOptions; static unsigned m_fontOptions;