From 916266a7b3538c3d31abe245ee84e691934fab40 Mon Sep 17 00:00:00 2001 From: David Faure Date: Sun, 8 Oct 2017 21:20:24 +0200 Subject: QMimeDatabase: ensure mutex is locked in provider() This wasn't the case when called from QMimeType, or some QMimeDatabase methods. Now fixed. Change-Id: Ifd515c1520482e4a23c399f1f773269659c92359 Reviewed-by: Thiago Macieira --- src/corelib/mimetypes/qmimedatabase.cpp | 52 ++++++++++++++++++++++++++++----- src/corelib/mimetypes/qmimedatabase_p.h | 17 +++++++++-- src/corelib/mimetypes/qmimetype.cpp | 20 ++++++------- 3 files changed, 69 insertions(+), 20 deletions(-) (limited to 'src/corelib/mimetypes') diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp index 687f0b3e03..ed8bad0d83 100644 --- a/src/corelib/mimetypes/qmimedatabase.cpp +++ b/src/corelib/mimetypes/qmimedatabase.cpp @@ -81,6 +81,7 @@ QMimeDatabasePrivate::~QMimeDatabasePrivate() QMimeProviderBase *QMimeDatabasePrivate::provider() { + Q_ASSERT(!mutex.tryLock()); // caller should have locked mutex if (!m_provider) { QMimeProviderBase *binaryProvider = new QMimeBinaryProvider(this); if (binaryProvider->isValid()) { @@ -93,12 +94,6 @@ QMimeProviderBase *QMimeDatabasePrivate::provider() return m_provider; } -void QMimeDatabasePrivate::setProvider(QMimeProviderBase *theProvider) -{ - delete m_provider; - m_provider = theProvider; -} - /*! \internal Returns a MIME type or an invalid one if none found @@ -118,6 +113,47 @@ QStringList QMimeDatabasePrivate::mimeTypeForFileName(const QString &fileName) return matchingMimeTypes; } +QMimeGlobMatchResult QMimeDatabasePrivate::findByFileName(const QString &fileName) +{ + return provider()->findByFileName(fileName); +} + +void QMimeDatabasePrivate::loadMimeTypePrivate(QMimeTypePrivate &mimePrivate) +{ + QMutexLocker locker(&mutex); + provider()->loadMimeTypePrivate(mimePrivate); +} + +void QMimeDatabasePrivate::loadGenericIcon(QMimeTypePrivate &mimePrivate) +{ + QMutexLocker locker(&mutex); + provider()->loadGenericIcon(mimePrivate); +} + +void QMimeDatabasePrivate::loadIcon(QMimeTypePrivate &mimePrivate) +{ + QMutexLocker locker(&mutex); + provider()->loadIcon(mimePrivate); +} + +QStringList QMimeDatabasePrivate::parents(const QString &mimeName) +{ + QMutexLocker locker(&mutex); + return provider()->parents(mimeName); +} + +QStringList QMimeDatabasePrivate::listAliases(const QString &mimeName) +{ + QMutexLocker locker(&mutex); + return provider()->listAliases(mimeName); +} + +bool QMimeDatabasePrivate::mimeInherits(const QString &mime, const QString &parent) +{ + QMutexLocker locker(&mutex); + return inherits(mime, parent); +} + static inline bool isTextFile(const QByteArray &data) { // UTF16 byte order marks @@ -460,7 +496,7 @@ QList QMimeDatabase::mimeTypesForFileName(const QString &fileName) co QString QMimeDatabase::suffixForFileName(const QString &fileName) const { QMutexLocker locker(&d->mutex); - return d->provider()->findByFileName(QFileInfo(fileName).fileName()).m_foundSuffix; + return d->findByFileName(QFileInfo(fileName).fileName()).m_foundSuffix; } /*! @@ -550,6 +586,7 @@ QMimeType QMimeDatabase::mimeTypeForUrl(const QUrl &url) const */ QMimeType QMimeDatabase::mimeTypeForFileNameAndData(const QString &fileName, QIODevice *device) const { + QMutexLocker locker(&d->mutex); int accuracy = 0; const bool openedByUs = !device->isOpen() && device->open(QIODevice::ReadOnly); const QMimeType result = d->mimeTypeForFileNameAndData(fileName, device, &accuracy); @@ -576,6 +613,7 @@ QMimeType QMimeDatabase::mimeTypeForFileNameAndData(const QString &fileName, QIO */ QMimeType QMimeDatabase::mimeTypeForFileNameAndData(const QString &fileName, const QByteArray &data) const { + QMutexLocker locker(&d->mutex); QBuffer buffer(const_cast(&data)); buffer.open(QIODevice::ReadOnly); int accuracy = 0; diff --git a/src/corelib/mimetypes/qmimedatabase_p.h b/src/corelib/mimetypes/qmimedatabase_p.h index 3f63f5f103..5dfcf31237 100644 --- a/src/corelib/mimetypes/qmimedatabase_p.h +++ b/src/corelib/mimetypes/qmimedatabase_p.h @@ -77,9 +77,6 @@ public: static QMimeDatabasePrivate *instance(); - QMimeProviderBase *provider(); - void setProvider(QMimeProviderBase *theProvider); - inline QString defaultMimeType() const { return m_defaultMimeType; } bool inherits(const QString &mime, const QString &parent); @@ -91,8 +88,22 @@ public: QMimeType mimeTypeForFileNameAndData(const QString &fileName, QIODevice *device, int *priorityPtr); QMimeType findByData(const QByteArray &data, int *priorityPtr); QStringList mimeTypeForFileName(const QString &fileName); + QMimeGlobMatchResult findByFileName(const QString &fileName); + + // API for QMimeType. Takes care of locking the mutex. + void loadMimeTypePrivate(QMimeTypePrivate &mimePrivate); + void loadGenericIcon(QMimeTypePrivate &mimePrivate); + void loadIcon(QMimeTypePrivate &mimePrivate); + QStringList parents(const QString &mimeName); + QStringList listAliases(const QString &mimeName); + bool mimeInherits(const QString &mime, const QString &parent); + +private: + QMimeProviderBase *provider(); mutable QMimeProviderBase *m_provider; + +public: const QString m_defaultMimeType; QMutex mutex; }; diff --git a/src/corelib/mimetypes/qmimetype.cpp b/src/corelib/mimetypes/qmimetype.cpp index 28113babfe..668b22e7cf 100644 --- a/src/corelib/mimetypes/qmimetype.cpp +++ b/src/corelib/mimetypes/qmimetype.cpp @@ -256,7 +256,7 @@ QString QMimeType::name() const */ QString QMimeType::comment() const { - QMimeDatabasePrivate::instance()->provider()->loadMimeTypePrivate(*d); + QMimeDatabasePrivate::instance()->loadMimeTypePrivate(*d); QStringList languageList; languageList << QLocale().name(); @@ -296,7 +296,7 @@ QString QMimeType::comment() const */ QString QMimeType::genericIconName() const { - QMimeDatabasePrivate::instance()->provider()->loadGenericIcon(*d); + QMimeDatabasePrivate::instance()->loadGenericIcon(*d); if (d->genericIconName.isEmpty()) { // From the spec: // If the generic icon name is empty (not specified by the mimetype definition) @@ -324,7 +324,7 @@ QString QMimeType::genericIconName() const */ QString QMimeType::iconName() const { - QMimeDatabasePrivate::instance()->provider()->loadIcon(*d); + QMimeDatabasePrivate::instance()->loadIcon(*d); if (d->iconName.isEmpty()) { // Make default icon name from the mimetype name d->iconName = name(); @@ -344,7 +344,7 @@ QString QMimeType::iconName() const */ QStringList QMimeType::globPatterns() const { - QMimeDatabasePrivate::instance()->provider()->loadMimeTypePrivate(*d); + QMimeDatabasePrivate::instance()->loadMimeTypePrivate(*d); return d->globPatterns; } @@ -368,12 +368,12 @@ QStringList QMimeType::globPatterns() const */ QStringList QMimeType::parentMimeTypes() const { - return QMimeDatabasePrivate::instance()->provider()->parents(d->name); + return QMimeDatabasePrivate::instance()->parents(d->name); } static void collectParentMimeTypes(const QString &mime, QStringList &allParents) { - const QStringList parents = QMimeDatabasePrivate::instance()->provider()->parents(mime); + const QStringList parents = QMimeDatabasePrivate::instance()->parents(mime); for (const QString &parent : parents) { // I would use QSet, but since order matters I better not if (!allParents.contains(parent)) @@ -425,7 +425,7 @@ QStringList QMimeType::allAncestors() const */ QStringList QMimeType::aliases() const { - return QMimeDatabasePrivate::instance()->provider()->listAliases(d->name); + return QMimeDatabasePrivate::instance()->listAliases(d->name); } /*! @@ -439,7 +439,7 @@ QStringList QMimeType::aliases() const */ QStringList QMimeType::suffixes() const { - QMimeDatabasePrivate::instance()->provider()->loadMimeTypePrivate(*d); + QMimeDatabasePrivate::instance()->loadMimeTypePrivate(*d); QStringList result; for (const QString &pattern : qAsConst(d->globPatterns)) { @@ -480,7 +480,7 @@ QString QMimeType::preferredSuffix() const */ QString QMimeType::filterString() const { - QMimeDatabasePrivate::instance()->provider()->loadMimeTypePrivate(*d); + QMimeDatabasePrivate::instance()->loadMimeTypePrivate(*d); QString filter; if (!d->globPatterns.empty()) { @@ -508,7 +508,7 @@ bool QMimeType::inherits(const QString &mimeTypeName) const { if (d->name == mimeTypeName) return true; - return QMimeDatabasePrivate::instance()->inherits(d->name, mimeTypeName); + return QMimeDatabasePrivate::instance()->mimeInherits(d->name, mimeTypeName); } #ifndef QT_NO_DEBUG_STREAM -- cgit v1.2.3