From a6ffdbe30c49fa1ede0d147531b89d121d00fa94 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 7 Oct 2019 05:30:54 +0200 Subject: [PATCH 1/7] QTextCodec: try to work around an ICC 19 bug ICC 19 barfs on the TextCodecsMutexLocker class because it doesn't have a user-provided default ctor: ../../corelib/codecs/qtextcodec.cpp(543): error #854: const variable locker requires an initializer -- class TextCodecsMutexLocker has no user-provided default constructor [...] But the class doesn't have members that would delete the implictly-declared default ctor, so no user-provided default ctor should be necessary: The only member is the result of qt_unique_lock(), which is std::unique_lock, which does have a default ctor. We conclude that this is a compiler bug, and work around it with the introduction of a user-provided default ctor. Fix brace placement as a drive-by. Fixes: QTBUG-78844 Change-Id: I1f5a326afd68138fbebad506ba9aa1926f1afb85 Reviewed-by: Thiago Macieira --- src/corelib/codecs/qtextcodec.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp index 14f9abc28a9..06fd88da90c 100644 --- a/src/corelib/codecs/qtextcodec.cpp +++ b/src/corelib/codecs/qtextcodec.cpp @@ -103,10 +103,13 @@ typedef QList::ConstIterator ByteArrayListConstIt; Q_GLOBAL_STATIC(QRecursiveMutex, textCodecsMutex); -class TextCodecsMutexLocker { +class TextCodecsMutexLocker +{ using Lock = decltype(qt_unique_lock(std::declval())); // ### FIXME: this is used when textCodecsMutex already == nullptr const Lock lock = qt_unique_lock(textCodecsMutex()); +public: + TextCodecsMutexLocker() {} // required d/t an ICC 19 bug }; #if !QT_CONFIG(icu) From 38cf346bd70de6aaabfbf66ba159919591ce9098 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Mon, 7 Oct 2019 11:19:01 +0200 Subject: [PATCH 2/7] QMacStyle::drawControl - lift the pool declaration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit out of switch/case - can help in case some NSControl is using autorelease and an application is calling drawControl too often. Fixes: QTBUG-78761 Change-Id: I2b55d533f52db16703dcc965920f4316fdf76734 Reviewed-by: Tor Arne Vestbø --- src/plugins/styles/mac/qmacstyle_mac.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index b2bcdb3e5b5..0a216e540d4 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -3462,6 +3462,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter { Q_D(const QMacStyle); const AppearanceSync sync; + const QMacAutoReleasePool pool; QMacCGContext cg(p); QWindow *window = w && w->window() ? w->window()->windowHandle() : nullptr; d->resolveCurrentNSView(window); @@ -4326,7 +4327,6 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter break; case CE_ProgressBarContents: if (const QStyleOptionProgressBar *pb = qstyleoption_cast(opt)) { - QMacAutoReleasePool pool; const bool isIndeterminate = (pb->minimum == 0 && pb->maximum == 0); const bool vertical = pb->orientation == Qt::Vertical; const bool inverted = pb->invertedAppearance; From af8f3c5da4b842973f7e2b279fe21c486fcee696 Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Tue, 1 Oct 2019 17:12:42 +0200 Subject: [PATCH 3/7] Add libfuzzer test for QTextLayout::beginLayout() Task-number: QTBUG-77819 Change-Id: I34e9cbaa615896222bcf947012cfed9f6c3186c7 Reviewed-by: Rainer Keller --- .../qtextlayout/beginLayout/beginLayout.pro | 3 ++ .../gui/text/qtextlayout/beginLayout/main.cpp | 36 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 tests/libfuzzer/gui/text/qtextlayout/beginLayout/beginLayout.pro create mode 100644 tests/libfuzzer/gui/text/qtextlayout/beginLayout/main.cpp diff --git a/tests/libfuzzer/gui/text/qtextlayout/beginLayout/beginLayout.pro b/tests/libfuzzer/gui/text/qtextlayout/beginLayout/beginLayout.pro new file mode 100644 index 00000000000..c9b14f6caf1 --- /dev/null +++ b/tests/libfuzzer/gui/text/qtextlayout/beginLayout/beginLayout.pro @@ -0,0 +1,3 @@ +QT += widgets +SOURCES += main.cpp +LIBS += -fsanitize=fuzzer diff --git a/tests/libfuzzer/gui/text/qtextlayout/beginLayout/main.cpp b/tests/libfuzzer/gui/text/qtextlayout/beginLayout/main.cpp new file mode 100644 index 00000000000..dfb95592410 --- /dev/null +++ b/tests/libfuzzer/gui/text/qtextlayout/beginLayout/main.cpp @@ -0,0 +1,36 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +extern "C" int LLVMFuzzerTestOneInput(const char *Data, size_t Size) { + QTextLayout tl(QByteArray::fromRawData(Data, Size)); + tl.beginLayout(); + tl.endLayout(); + return 0; +} From b8a17ee13559a38c4cb2f20f91c39ea39d5ded9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 7 Oct 2019 12:28:08 +0200 Subject: [PATCH 4/7] Fix double free when debug printing QFont with non-default verbosity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ieb7fa19e8bdd98f5283f7f6d8751e6532c8e0fc4 Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Tor Arne Vestbø --- src/gui/text/qfont.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index efc79a17839..76fde5388c5 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -3176,8 +3176,7 @@ QDebug operator<<(QDebug stream, const QFont &font) QDebug debug(&fontDescription); debug.nospace(); - QFontPrivate priv; - const QFont defaultFont(&priv); + const QFont defaultFont(new QFontPrivate); for (int property = QFont::FamilyResolved; property < QFont::AllPropertiesResolved; property <<= 1) { const bool resolved = (font.resolve_mask & property) != 0; From 6906b0647a2e1389a9eeeef0dd0f6354c9dd4206 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Sat, 5 Oct 2019 13:28:55 +0200 Subject: [PATCH 5/7] macOS: Pass required parameters to NSOpenSavePanelDelegate callbacks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I0e0322734a077e4ee948128f3ba6c074514ccbb9 Reviewed-by: Volker Hilsheimer Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index 5f32400af04..03677ef0bcd 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -214,7 +214,7 @@ static QString strippedText(QString s) NSString *filepath = info.filePath().toNSString(); NSURL *url = [NSURL fileURLWithPath:filepath isDirectory:info.isDir()]; bool selectable = (mOptions->acceptMode() == QFileDialogOptions::AcceptSave) - || [self panel:nil shouldEnableURL:url]; + || [self panel:mOpenPanel shouldEnableURL:url]; [self updateProperties]; [mSavePanel setNameFieldStringValue:selectable ? info.fileName().toNSString() : @""]; @@ -233,7 +233,7 @@ static QString strippedText(QString s) NSString *filepath = info.filePath().toNSString(); NSURL *url = [NSURL fileURLWithPath:filepath isDirectory:info.isDir()]; bool selectable = (mOptions->acceptMode() == QFileDialogOptions::AcceptSave) - || [self panel:nil shouldEnableURL:url]; + || [self panel:mSavePanel shouldEnableURL:url]; [mSavePanel setDirectoryURL: [NSURL fileURLWithPath:mCurrentDir]]; [mSavePanel setNameFieldStringValue:selectable ? info.fileName().toNSString() : @""]; @@ -263,7 +263,7 @@ static QString strippedText(QString s) NSString *filepath = info.filePath().toNSString(); NSURL *url = [NSURL fileURLWithPath:filepath isDirectory:info.isDir()]; bool selectable = (mOptions->acceptMode() == QFileDialogOptions::AcceptSave) - || [self panel:nil shouldEnableURL:url]; + || [self panel:mSavePanel shouldEnableURL:url]; [self updateProperties]; [mSavePanel setDirectoryURL: [NSURL fileURLWithPath:mCurrentDir]]; From c962c77044901a08d1ec15ffec81d48f87a35b4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 3 Oct 2019 16:07:37 +0200 Subject: [PATCH 6/7] CoreText: Warn the user when family alias lookup slows down the application If the user specifies a font family in their application that doesn't exist in the system, or one that uses the localized family name, we will end up resolving the family alias for all fonts in the system, which typically adds 600-800ms of startup time. Let the user know when this happens. Change-Id: Id8d6f55028e37f681ec4a686df25d33240b5a30f Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/text/qfontdatabase.cpp | 2 +- src/gui/text/qplatformfontdatabase.h | 2 +- .../mac/qcoretextfontdatabase.mm | 50 +++++++++++++++++-- .../mac/qcoretextfontdatabase_p.h | 2 +- 4 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index ce6bb0c3473..261e1d831b0 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -2684,7 +2684,7 @@ QFontEngine *QFontDatabase::findFont(const QFontDef &request, int script) QtFontDesc desc; QList blackListed; int index = match(multi ? QChar::Script_Common : script, request, family_name, foundry_name, &desc, blackListed); - if (index < 0 && QGuiApplicationPrivate::platformIntegration()->fontDatabase()->populateFamilyAliases()) { + if (index < 0 && QGuiApplicationPrivate::platformIntegration()->fontDatabase()->populateFamilyAliases(family_name)) { // We populated familiy aliases (e.g. localized families), so try again index = match(multi ? QChar::Script_Common : script, request, family_name, foundry_name, &desc, blackListed); } diff --git a/src/gui/text/qplatformfontdatabase.h b/src/gui/text/qplatformfontdatabase.h index 38ba7f10b23..f79c5db6251 100644 --- a/src/gui/text/qplatformfontdatabase.h +++ b/src/gui/text/qplatformfontdatabase.h @@ -104,7 +104,7 @@ class Q_GUI_EXPORT QPlatformFontDatabase public: virtual ~QPlatformFontDatabase(); virtual void populateFontDatabase(); - virtual bool populateFamilyAliases() { return false; } + virtual bool populateFamilyAliases(const QString &missingFamily) { Q_UNUSED(missingFamily); return false; } virtual void populateFamily(const QString &familyName); virtual void invalidate(); diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index 201a82864f2..4887a501bac 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -48,6 +48,8 @@ #import #endif +#include + #include "qcoretextfontdatabase_p.h" #include "qfontengine_coretext_p.h" #if QT_CONFIG(settings) @@ -113,39 +115,77 @@ QCoreTextFontDatabase::~QCoreTextFontDatabase() void QCoreTextFontDatabase::populateFontDatabase() { + qCDebug(lcQpaFonts) << "Populating font database..."; + QElapsedTimer elapsed; + if (lcQpaFonts().isDebugEnabled()) + elapsed.start(); + QCFType familyNames = CTFontManagerCopyAvailableFontFamilyNames(); for (NSString *familyName in familyNames.as()) QPlatformFontDatabase::registerFontFamily(QString::fromNSString(familyName)); + qCDebug(lcQpaFonts) << "Populating available families took" << elapsed.restart() << "ms"; + // Force creating the theme fonts to get the descriptors in m_systemFontDescriptors if (m_themeFonts.isEmpty()) (void)themeFonts(); + qCDebug(lcQpaFonts) << "Resolving theme fonts took" << elapsed.restart() << "ms"; + Q_FOREACH (CTFontDescriptorRef fontDesc, m_systemFontDescriptors) populateFromDescriptor(fontDesc); + qCDebug(lcQpaFonts) << "Populating system descriptors took" << elapsed.restart() << "ms"; + Q_ASSERT(!m_hasPopulatedAliases); } -bool QCoreTextFontDatabase::populateFamilyAliases() +bool QCoreTextFontDatabase::populateFamilyAliases(const QString &missingFamily) { #if defined(Q_OS_MACOS) if (m_hasPopulatedAliases) return false; + // There's no API to go from a localized family name to its non-localized + // name, so we have to resort to enumerating all the available fonts and + // doing a reverse lookup. + + qCDebug(lcQpaFonts) << "Populating family aliases..."; + QElapsedTimer elapsed; + elapsed.start(); + + QString nonLocalizedMatch; QCFType familyNames = CTFontManagerCopyAvailableFontFamilyNames(); + NSFontManager *fontManager = NSFontManager.sharedFontManager; for (NSString *familyName in familyNames.as()) { - NSFontManager *fontManager = [NSFontManager sharedFontManager]; NSString *localizedFamilyName = [fontManager localizedNameForFamily:familyName face:nil]; if (![localizedFamilyName isEqual:familyName]) { - QPlatformFontDatabase::registerAliasToFontFamily( - QString::fromNSString(familyName), - QString::fromNSString(localizedFamilyName)); + QString nonLocalizedFamily = QString::fromNSString(familyName); + QString localizedFamily = QString::fromNSString(localizedFamilyName); + QPlatformFontDatabase::registerAliasToFontFamily(nonLocalizedFamily, localizedFamily); + if (localizedFamily == missingFamily) + nonLocalizedMatch = nonLocalizedFamily; } } m_hasPopulatedAliases = true; + + if (lcQpaFonts().isWarningEnabled()) { + QString warningMessage; + QDebug msg(&warningMessage); + + msg << "Populating font family aliases took" << elapsed.restart() << "ms."; + if (!nonLocalizedMatch.isNull()) + msg << "Replace uses of" << missingFamily << "with its non-localized name" << nonLocalizedMatch; + else + msg << "Replace uses of missing font family" << missingFamily << "with one that exists"; + msg << "to avoid this cost."; + + qCWarning(lcQpaFonts) << qPrintable(warningMessage); + } + return true; #else + Q_UNUSED(missingFamily); return false; #endif } diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h index 45e74b99be4..69ff454d1e9 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h @@ -71,7 +71,7 @@ public: QCoreTextFontDatabase(); ~QCoreTextFontDatabase(); void populateFontDatabase() override; - bool populateFamilyAliases() override; + bool populateFamilyAliases(const QString &missingFamily) override; void populateFamily(const QString &familyName) override; void invalidate() override; From 3425c9c6d7f7915e6f7931da46105b36245e86ad Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Thu, 29 Aug 2019 09:36:53 +0100 Subject: [PATCH 7/7] Handle context loss in QPlatformBackingStore This powers a QQuickWidget and we also need to reset the context if we get a context loss event. Change-Id: Id8b7112606670985860069c2bb11cf141b3ac723 Reviewed-by: Laszlo Agocs --- src/gui/painting/qplatformbackingstore.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp index 601dc97be10..45e90bd99b1 100644 --- a/src/gui/painting/qplatformbackingstore.cpp +++ b/src/gui/painting/qplatformbackingstore.cpp @@ -338,7 +338,16 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i } } - if (!d_ptr->context->makeCurrent(window)) { + bool current = d_ptr->context->makeCurrent(window); + + if (!current && !d_ptr->context->isValid()) { + delete d_ptr->blitter; + d_ptr->blitter = nullptr; + d_ptr->textureId = 0; + current = d_ptr->context->create() && d_ptr->context->makeCurrent(window); + } + + if (!current) { qCWarning(lcQpaBackingStore, "composeAndFlush: makeCurrent() failed"); return; }