From 7c5cf8b2bdd49f9f19a6d2db5f5f12372ca6cfca Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Sat, 17 Sep 2016 11:54:29 +0200 Subject: Fix bootstrap applications crashing when QT_MESSAGE_PATTERN contains %{backtrace} tokens[i] was left uninitialized. This could cause a crash when moc produces a qWarning. Task-number: QTBUG-56045 Change-Id: I6fba933005edd29756f0d6b1cfe53243254ac7b2 Reviewed-by: Marc Mutz Reviewed-by: Thiago Macieira --- src/corelib/global/qlogging.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index 6cd2d7914b..eb26b6198d 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -1133,6 +1133,7 @@ void QMessagePattern::setPattern(const QString &pattern) backtraceArgs.append(backtraceParams); #else error += QStringLiteral("QT_MESSAGE_PATTERN: %{backtrace} is not supported by this Qt build\n"); + tokens[i] = ""; #endif } -- cgit v1.2.3 From f050f2180ffb8298de802b33ad9f017312df1815 Mon Sep 17 00:00:00 2001 From: Konstantin Tokarev Date: Sat, 6 Aug 2016 17:02:31 +0300 Subject: Describe meaning of typographic units in QRawFont documentation Text is copied from corresponding QFontMetrics methods. Change-Id: Ife79e0d1b06ca3f691f2fd8bd796b41aeaa76954 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/text/qrawfont.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src') diff --git a/src/gui/text/qrawfont.cpp b/src/gui/text/qrawfont.cpp index 9e045f91c3..66d16d6068 100644 --- a/src/gui/text/qrawfont.cpp +++ b/src/gui/text/qrawfont.cpp @@ -310,6 +310,13 @@ bool QRawFont::operator==(const QRawFont &other) const /*! Returns the ascent of this QRawFont in pixel units. + The ascent of a font is the distance from the baseline to the + highest position characters extend to. In practice, some font + designers break this rule, e.g. when they put more than one accent + on top of a character, or to accommodate an unusual character in + an exotic language, so it is possible (though rare) that this + value will be too small. + \sa QFontMetricsF::ascent() */ qreal QRawFont::ascent() const @@ -320,6 +327,11 @@ qreal QRawFont::ascent() const /*! Returns the descent of this QRawFont in pixel units. + The descent is the distance from the base line to the lowest point + characters extend to. In practice, some font designers break this rule, + e.g. to accommodate an unusual character in an exotic language, so + it is possible (though rare) that this value will be too small. + \sa QFontMetricsF::descent() */ qreal QRawFont::descent() const @@ -330,6 +342,8 @@ qreal QRawFont::descent() const /*! Returns the xHeight of this QRawFont in pixel units. + This is often but not always the same as the height of the character 'x'. + \sa QFontMetricsF::xHeight() */ qreal QRawFont::xHeight() const @@ -340,6 +354,8 @@ qreal QRawFont::xHeight() const /*! Returns the leading of this QRawFont in pixel units. + This is the natural inter-line spacing. + \sa QFontMetricsF::leading() */ qreal QRawFont::leading() const -- cgit v1.2.3 From abe8b4ab9b5243b477c72f3e900d4f6cca79b5c5 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 21 Sep 2016 15:21:00 +0200 Subject: Q(Font|Color|File)Dialog: Fix several UBs (invalid cast/member call) in Private::canBeNativeDialog() Found by UBSan: qfontdialog_p.h:77:5: runtime error: downcast of address 0x7ffc3ceadc90 which does not point to an object of type 'QFontDialog' 0x7ffc3ceadc90: note: object is of type 'QDialog' fc 7f 00 00 38 5f a8 27 fc 2a 00 00 60 e2 14 02 00 00 00 00 10 61 a8 27 fc 2a 00 00 00 00 00 00 ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'QDialog' #0 0x2afc24d29490 in QFontDialogPrivate::q_func() const qfontdialog_p.h:77 #1 0x2afc24d29490 in QFontDialogPrivate::canBeNativeDialog() const qfontdialog.cpp:1033 #2 0x2afc24c93f56 in QDialog::setVisible(bool) qdialog.cpp:696 #3 0x2afc24c7b27a in QDialog::~QDialog() qdialog.cpp:357 #4 0x2afc24d286a6 in QFontDialog::~QFontDialog() qfontdialog.cpp:339 #5 0x2afc24d481a2 in QFontDialogPrivate::getFont(bool*, QFont const&, QWidget*, QString const&, QFlags) qfontdialog.cpp:402 #6 0x2afc24d483f1 in QFontDialog::getFont(bool*, QWidget*) qfontdialog.cpp:396 #7 0x407652 in tst_QFontDialog::testGetFont() tst_qfontdialog.cpp:120 qcolordialog.cpp:86:5: runtime error: downcast of address 0x7ffdf50c1ec0 which does not point to an object of type 'QColorDialog' 0x7ffdf50c1ec0: note: object is of type 'QDialog' fd 7f 00 00 d8 6e c7 23 b7 2a 00 00 50 c1 af 01 00 00 00 00 b0 70 c7 23 b7 2a 00 00 00 00 1a 1e ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'QDialog' #0 0x2ab720e4ec97 in QColorDialogPrivate::q_func() const qcolordialog.cpp:86 #1 0x2ab720e4ec97 in QColorDialogPrivate::canBeNativeDialog() const qcolordialog.cpp:1865 #2 0x2ab720e84ed6 in QDialog::setVisible(bool) qdialog.cpp:696 #3 0x2ab720e6c1fa in QDialog::~QDialog() qdialog.cpp:357 #4 0x2ab720e2b276 in QColorDialog::~QColorDialog() qcolordialog.cpp:2187 #5 0x2ab720e5e2c6 in QColorDialog::getColor(QColor const&, QWidget*, QString const&, QFlags) qcolordialog.cpp:2148 #6 0x2ab720e5e473 in QColorDialog::getRgba(unsigned int, bool*, QWidget*) qcolordialog.cpp:2176 #7 0x407180 in tst_QColorDialog::testGetRgba() tst_qcolordialog.cpp:118 qfiledialog_p.h:112:5: runtime error: downcast of address 0x7ffd6858cc60 which does not point to an object of type 'QFileDialog' 0x7ffd6858cc60: note: object is of type 'QDialog' a1 2b 00 00 d8 1e 5e 0c a1 2b 00 00 b0 af 01 20 a1 2b 00 00 b0 20 5e 0c a1 2b 00 00 00 00 46 00 ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'QDialog' #0 0x2ba10980a9e7 in QFileDialogPrivate::q_func() const qfiledialog_p.h:112 #1 0x2ba10980a9e7 in QFileDialogPrivate::canBeNativeDialog() const qfiledialog.cpp:695 #2 0x2ba1097efe36 in QDialog::setVisible(bool) qdialog.cpp:696 #3 0x2ba1097d715a in QDialog::~QDialog() qdialog.cpp:357 #4 0x2ba109854c4b in QFileDialog::~QFileDialog() qfiledialog.cpp:380 #5 0x4179dc in tst_QFiledialog::init() tst_qfiledialog.cpp:175 Fix by replacing Q_Q with the the equivalent expression for QDialog. We can't re-use QDialogPrivate::q_func() here, since that is private, and probably should stay like that. Also fix an invalid member call in QColorDialogPrivate::canBeNativeDialog(): qcolordialog.cpp:2050:5: runtime error: member call on address 0x7ffdf50c1ec0 which does not point to an object of type 'QColorDialog' 0x7ffdf50c1ec0: note: object is of type 'QDialog' fd 7f 00 00 d8 6e c7 23 b7 2a 00 00 50 c1 af 01 00 00 00 00 b0 70 c7 23 b7 2a 00 00 00 00 1a 1e ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'QDialog' #0 0x2ab720e4e5ea in QColorDialog::options() const qcolordialog.cpp:2050 #1 0x2ab720e4e8c8 in QColorDialogPrivate::canBeNativeDialog() const qcolordialog.cpp:1870 #2 0x2ab720e84ed6 in QDialog::setVisible(bool) qdialog.cpp:696 #3 0x2ab720e6c1fa in QDialog::~QDialog() qdialog.cpp:357 #4 0x2ab720e2b276 in QColorDialog::~QColorDialog() qcolordialog.cpp:2187 #5 0x2ab720e5e2c6 in QColorDialog::getColor(QColor const&, QWidget*, QString const&, QFlags) qcolordialog.cpp:2148 #6 0x2ab720e5e473 in QColorDialog::getRgba(unsigned int, bool*, QWidget*) qcolordialog.cpp:2176 #7 0x407180 in tst_QColorDialog::testGetRgba() tst_qcolordialog.cpp:118 by accessing the data member directly instead of through the Public API. Fix the same code in QFileDialog, even though the autotest coverage is too limited for UBSan to point that one out explicitly. Change-Id: Idd278744961435e417d91fb2f89b6d91a94e0c71 Reviewed-by: Friedemann Kleint --- src/widgets/dialogs/qfontdialog.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/dialogs/qfontdialog.cpp b/src/widgets/dialogs/qfontdialog.cpp index 6644f26ad0..3ef844346b 100644 --- a/src/widgets/dialogs/qfontdialog.cpp +++ b/src/widgets/dialogs/qfontdialog.cpp @@ -1033,7 +1033,9 @@ void QFontDialog::done(int result) bool QFontDialogPrivate::canBeNativeDialog() const { - Q_Q(const QFontDialog); + // Don't use Q_Q here! This function is called from ~QDialog, + // so Q_Q calling q_func() invokes undefined behavior (invalid cast in q_func()). + const QDialog * const q = static_cast(q_ptr); if (nativeDialogInUse) return true; if (q->testAttribute(Qt::WA_DontShowOnScreen)) -- cgit v1.2.3 From f6cb8b1af8f15a06898c5c71f81c64779d9478f6 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 20 Sep 2016 15:32:17 +0200 Subject: QGraphicsScene: Fix UB (invalid cast) in removeItemHelper() The variable 'item' may or may not contain a QGraphicsObject pointer. Using static_cast on an 'item' that isn't, is UB. Found by UBSan (which failed to print a message, but the function names gave it away): [...] #6 #7 0x00002b18813bec05 in __ubsan::checkDynamicType(void*, void*, unsigned long) () from /opt/gcc/trunk/lib64/libubsan.so.0 #8 0x00002b18813be0c3 in HandleDynamicTypeCacheMiss(__ubsan::DynamicTypeCacheMissData*, unsigned long, unsigned long, __ubsan::ReportOptions) () from /opt/gcc/trunk/lib64/libubsan.so.0 #9 0x00002b18813be783 in __ubsan_handle_dynamic_type_cache_miss () from /opt/gcc/trunk/lib64/libubsan.so.0 #10 0x00002b1875e71d4d in QGraphicsScenePrivate::removeItemHelper(QGraphicsItem*) () at /home/marc/Qt/qt5/qtbase/src/widgets/graphicsview/qgraphicsscene.cpp:720 #11 0x00002b1875e731ef in QGraphicsScene::removeItem(QGraphicsItem*) () at /home/marc/Qt/qt5/qtbase/src/widgets/graphicsview/qgraphicsscene.cpp:2929 #12 0x00002b1875e6d05f in QGraphicsScenePrivate::removeItemHelper(QGraphicsItem*) () at /home/marc/Qt/qt5/qtbase/src/widgets/graphicsview/qgraphicsscene.cpp:604 #13 0x00002b1875e731ef in QGraphicsScene::removeItem(QGraphicsItem*) () at /home/marc/Qt/qt5/qtbase/src/widgets/graphicsview/qgraphicsscene.cpp:2929 #14 0x00002b1875e73e68 in QGraphicsScene::addItem(QGraphicsItem*) () at /home/marc/Qt/qt5/qtbase/src/widgets/graphicsview/qgraphicsscene.cpp:2505 #15 0x000000000043d34d in tst_QGraphicsWidget::fontPropagationSceneChange() () at /home/marc/Qt/qt5/qtbase/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp:941 [...] Fix by using QGraphicsItem::toGraphicsObject(). Yes, it's that simple... Change-Id: If04d1b62603cfd808cc7b64946da536c221a0c11 Reviewed-by: Friedemann Kleint --- src/widgets/graphicsview/qgraphicsscene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp index ad58aeb488..9e0be0c280 100644 --- a/src/widgets/graphicsview/qgraphicsscene.cpp +++ b/src/widgets/graphicsview/qgraphicsscene.cpp @@ -710,7 +710,7 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item) ++it; } - QGraphicsObject *dummy = static_cast(item); + QGraphicsObject *dummy = item->toGraphicsObject(); cachedTargetItems.removeOne(dummy); cachedItemGestures.remove(dummy); cachedAlreadyDeliveredGestures.remove(dummy); -- cgit v1.2.3 From 622681eb508ddb1bd51a39b6887beddb43218504 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 21 Sep 2016 10:01:01 +0200 Subject: QGraphicsScene: Fix UB (invalid cast) in Private::ungrabMouse() Found by UBSan: qgraphicsscene.cpp:1000:40: runtime error: downcast of address 0x2af0d4072b00 which does not point to an object of type 'QGraphicsWidget' 0x2af0d4072b00: note: object is of type 'QGraphicsObject' 00 00 00 00 30 f5 26 bd f0 2a 00 00 90 e1 05 d4 f0 2a 00 00 a8 e3 26 bd f0 2a 00 00 d0 33 0f d4 ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'QGraphicsObject' #0 0x2af0badf1305 in QGraphicsScenePrivate::ungrabMouse(QGraphicsItem*, bool) qgraphicsscene.cpp:1000 #1 0x2af0bae0fc24 in QGraphicsScenePrivate::removeItemHelper(QGraphicsItem*) qgraphicsscene.cpp:692 #2 0x2af0bacd21f6 in QGraphicsItem::~QGraphicsItem() qgraphicsitem.cpp:1555 #3 0x2af0bacd4c48 in QGraphicsObject::~QGraphicsObject() qgraphicsitem.cpp:7766 #4 0x2af0baf7e99c in QGraphicsWidget::~QGraphicsWidget() qgraphicswidget.cpp:231 #5 0x2af0baf7f8c0 in QGraphicsWidget::~QGraphicsWidget() qgraphicswidget.cpp:282 #6 0x2af0badcee34 in QGraphicsScene::clear() qgraphicsscene.cpp:2388 #7 0x2af0badcf3fc in QGraphicsScene::~QGraphicsScene() qgraphicsscene.cpp:1682 #8 0x4b26f0 in tst_QGraphicsWidget::popupMouseGrabber() tst_qgraphicswidget.cpp:47 Fix by using the existing graphics widget pointer, determined a line above to be equivalent to 'item', for the removePopup() function call instead of casting 'item' itself. The rest of removePopup() appears to be well-behaved and doesn't trigger any more UBSan errors, so it was indeed just the cast which was undefined, no member calls. Change-Id: Ia54da90262a7a02f527914a90b0208be0ffc0f0b Reviewed-by: Thiago Macieira --- src/widgets/graphicsview/qgraphicsscene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp index 9e0be0c280..ebc521eb00 100644 --- a/src/widgets/graphicsview/qgraphicsscene.cpp +++ b/src/widgets/graphicsview/qgraphicsscene.cpp @@ -987,7 +987,7 @@ void QGraphicsScenePrivate::ungrabMouse(QGraphicsItem *item, bool itemIsDying) // If the item is a popup, go via removePopup to ensure state // consistency and that it gets hidden correctly - beware that // removePopup() reenters this function to continue removing the grab. - removePopup((QGraphicsWidget *)item, itemIsDying); + removePopup(popupWidgets.constLast(), itemIsDying); return; } -- cgit v1.2.3 From 3ce07c3238b335a7019d8dfabde6bab3f16d342d Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 19 Sep 2016 12:04:53 +0200 Subject: Fix Myanmar text with some fonts In change db2764db3466221ad680d63ff2224cdd016fc351, we introduced the requirement of having specific OpenType tables available to certain fonts. Before, we would not require OpenType support to use a font for Myanmar text, for instance, since this was not listed as one of the languages requiring OpenType support. This patch simply brings back the limitation that fonts are only disqualified by missing tables if the language is one of the ones we know to require OpenType. Change-Id: I6f1ee2c8a068f9e183a36e24967f331dae96c14b Task-number: QTBUG-55569 Reviewed-by: Lars Knoll --- .../fontdatabases/fontconfig/qfontconfigdatabase.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index 8ebabf3419..1c2c3288a0 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -355,6 +355,12 @@ static const char *getFcFamilyForStyleHint(const QFont::StyleHint style) return stylehint; } +static inline bool requiresOpenType(int writingSystem) +{ + return ((writingSystem >= QFontDatabase::Syriac && writingSystem <= QFontDatabase::Sinhala) + || writingSystem == QFontDatabase::Khmer || writingSystem == QFontDatabase::Nko); +} + static void populateFromPattern(FcPattern *pattern) { QString familyName; @@ -419,7 +425,7 @@ static void populateFromPattern(FcPattern *pattern) FcLangResult langRes = FcLangSetHasLang(langset, lang); if (langRes != FcLangDifferentLang) { #if FC_VERSION >= 20297 - if (capabilityForWritingSystem[j] != Q_NULLPTR) { + if (capabilityForWritingSystem[j] != Q_NULLPTR && requiresOpenType(j)) { if (cap == Q_NULLPTR) capRes = FcPatternGetString(pattern, FC_CAPABILITY, 0, &cap); if (capRes == FcResultMatch && strstr(reinterpret_cast(cap), capabilityForWritingSystem[j]) == 0) -- cgit v1.2.3 From bde3384c9e3423b2b5fec565a32e49a1f796cd68 Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Mon, 22 Aug 2016 14:15:11 +0200 Subject: Doc: corrected reference to OpenSSL webpage Change-Id: I0314aac1e37615605a30d9dcc4962b9e7f883517 Reviewed-by: Venugopal Shivashankar --- src/network/doc/src/ssl.qdoc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/network/doc/src/ssl.qdoc b/src/network/doc/src/ssl.qdoc index 0129673ea2..5ad2cfafc6 100644 --- a/src/network/doc/src/ssl.qdoc +++ b/src/network/doc/src/ssl.qdoc @@ -36,10 +36,12 @@ the Secure Sockets Layer (SSL) protocol, using the OpenSSL Toolkit (\l{http://www.openssl.org/}) to perform encryption and protocol handling. + From Qt version 5.2 onwards, the officially supported version for OpenSSL + is 1.0.0 or later. Versions >= 0.9.7 and < 1.0.0 might work, but are not + guaranteed to work. + \annotatedlist ssl - See the \l {openssl-v1later}{OpenSSL Compatibility} page for information about the - versions of OpenSSL that are known to work with Qt. \section1 Enabling and Disabling SSL Support -- cgit v1.2.3 From 7c18cb4f83c4907b40abc0bf40c1573b02243b57 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 31 Aug 2016 09:41:12 +0200 Subject: QToolTip: Hide when close event is received Hide the tooltip when a window is requested to close in addition to focus/activation change. This fixes the tooltip blocking the shutdown of a Qt Quick Controls application. Task-number: QTBUG-55523 Change-Id: I09d10fc162ce125075b03c534412b488974d12b9 Reviewed-by: J-P Nurmi --- src/widgets/kernel/qtooltip.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/widgets/kernel/qtooltip.cpp b/src/widgets/kernel/qtooltip.cpp index 51bf6e4684..2f99f8836a 100644 --- a/src/widgets/kernel/qtooltip.cpp +++ b/src/widgets/kernel/qtooltip.cpp @@ -336,6 +336,7 @@ bool QTipLabel::eventFilter(QObject *o, QEvent *e) case QEvent::FocusIn: case QEvent::FocusOut: #endif + case QEvent::Close: // For QTBUG-55523 (QQC) specifically: Hide tooltip when windows are closed case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: -- cgit v1.2.3 From 29205c53e46fb2fc9f8063a46fd5ef5e9be532db Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 31 Aug 2016 09:36:34 +0200 Subject: QWindowPrivate::maybeQuitOnLastWindowClosed(): Skip tooltips Windows of type Qt::ToolTip should not prevent closing the application when checking for the last window. Task-number: QTBUG-55523 Change-Id: I47c51abe79bf6c857aba229960de95e1a23efb10 Reviewed-by: J-P Nurmi --- src/gui/kernel/qwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index bcd29b6fe1..2ff19f5175 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -2357,7 +2357,7 @@ void QWindowPrivate::maybeQuitOnLastWindowClosed() bool lastWindowClosed = true; for (int i = 0; i < list.size(); ++i) { QWindow *w = list.at(i); - if (!w->isVisible() || w->transientParent()) + if (!w->isVisible() || w->transientParent() || w->type() == Qt::ToolTip) continue; lastWindowClosed = false; break; -- cgit v1.2.3 From d95cb94baa6302bea6ad57a9690453e9b618421e Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Thu, 22 Sep 2016 17:04:29 +0200 Subject: Fix linear RGB16 gradients Writing to solid overwrites part of the gradient input messing up later lines. In particular repeating gradients tended to be broken. Tested by lancelot (once the baseline is correct). Change-Id: I64222048ba67b0424b44822f09ddc947973145a6 Reviewed-by: Eirik Aavitsland Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/gui/painting/qdrawhelper.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index ee3863ceb8..39ff4142b8 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -5638,15 +5638,16 @@ static void qt_gradient_quint16(int count, const QSpan *spans, void *userData) int yinc = int((linear.dy * data->m22 * gss) * FIXPT_SIZE); int off = int((((linear.dy * (data->m22 * qreal(0.5) + data->dy) + linear.off) * gss) * FIXPT_SIZE)); - QRgba64 oldColor = data->solid.color; + // Save the fillData since we overwrite it when setting solid.color. + QGradientData gradient = data->gradient; while (count--) { int y = spans->y; - data->solid.color = QRgba64::fromArgb32(qt_gradient_pixel_fixed(&data->gradient, yinc * y + off)); + data->solid.color = QRgba64::fromArgb32(qt_gradient_pixel_fixed(&gradient, yinc * y + off)); blend_color_rgb16(1, spans, userData); ++spans; } - data->solid.color = oldColor; + data->gradient = gradient; } else { blend_src_generic(count, spans, userData); -- cgit v1.2.3 From 456ae0dfeb7f537266995c66b180cddf0c587743 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 21 Sep 2016 19:06:53 -0700 Subject: QNetworkInterface: fix reporting of virtual interfaces on Linux We checked if we had seen the interface by looking into seenInterfaces and seenIndexes, but we never updated those variables with what we saw in this block. This fixes the reporting of PPP interfaces as well as TUN/TAP virtual interfaces. Change-Id: I33dc971f005a4848bb8ffffd1476830b8482b808 Reviewed-by: Edward Welbourne --- src/network/kernel/qnetworkinterface_unix.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/network/kernel/qnetworkinterface_unix.cpp b/src/network/kernel/qnetworkinterface_unix.cpp index eb73a2fb18..8ae36b56c2 100644 --- a/src/network/kernel/qnetworkinterface_unix.cpp +++ b/src/network/kernel/qnetworkinterface_unix.cpp @@ -352,6 +352,9 @@ static QList createInterfaces(ifaddrs *rawList) if (seenIndexes.contains(ifindex)) continue; + seenInterfaces.insert(name); + seenIndexes.append(ifindex); + QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate; interfaces << iface; iface->name = name; -- cgit v1.2.3 From 6a7b6c376be27390f359f0638f61147478323dae Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 23 Sep 2016 15:35:46 +0200 Subject: QApplication: Fix UB (invalid cast) in notify() Found by UBSan, which was so shocked that it crashed: #6 #7 __dynamic_cast () at ../../../../gcc/libstdc++-v3/libsupc++/dyncast.cc:50 #8 0x00002b9278fa1c3b in __ubsan::checkDynamicType(void*, void*, unsigned long) () from /opt/gcc/trunk/lib64/libubsan.so.0 #9 0x00002b9278fa10c3 in HandleDynamicTypeCacheMiss(__ubsan::DynamicTypeCacheMissData*, unsigned long, unsigned long, __ubsan::ReportOptions) () from /opt/gcc/trunk/lib64/libubsan.so.0 #10 0x00002b9278fa1783 in __ubsan_handle_dynamic_type_cache_miss () from /opt/gcc/trunk/lib64/libubsan.so.0 #11 0x00002b926c08ab8d in QApplication::notify(QObject*, QEvent*) () at /home/marc/Qt/qt5/qtbase/src/widgets/kernel/qapplication.cpp:3120 (full backtrace originates in tst_QWidget::testDeletionInEventHandlers(), testing key events). Fix is simple: just perform the cast before delivering the event. Change-Id: Ic26e36f47ef57e980c0dba00900927ff39fe6392 Reviewed-by: Thiago Macieira --- src/widgets/kernel/qapplication.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 917273e8cf..b64d6e2159 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -3178,11 +3178,11 @@ bool QApplication::notify(QObject *receiver, QEvent *e) key->accept(); else key->ignore(); - res = d->notify_helper(receiver, e); QWidget *w = isWidget ? static_cast(receiver) : 0; #ifndef QT_NO_GRAPHICSVIEW QGraphicsWidget *gw = isGraphicsWidget ? static_cast(receiver) : 0; #endif + res = d->notify_helper(receiver, e); if ((res && key->isAccepted()) /* -- cgit v1.2.3 From 82eb7d1537d4c1265575c62b4678d668d77a4d96 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 21 Sep 2016 15:21:00 +0200 Subject: Q(Color|File)Dialog: Fix several UBs (invalid cast/member call) in Private::canBeNativeDialog() Found by UBSan: qcolordialog.cpp:86:5: runtime error: downcast of address 0x7ffdf50c1ec0 which does not point to an object of type 'QColorDialog' 0x7ffdf50c1ec0: note: object is of type 'QDialog' fd 7f 00 00 d8 6e c7 23 b7 2a 00 00 50 c1 af 01 00 00 00 00 b0 70 c7 23 b7 2a 00 00 00 00 1a 1e ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'QDialog' #0 0x2ab720e4ec97 in QColorDialogPrivate::q_func() const qcolordialog.cpp:86 #1 0x2ab720e4ec97 in QColorDialogPrivate::canBeNativeDialog() const qcolordialog.cpp:1865 #2 0x2ab720e84ed6 in QDialog::setVisible(bool) qdialog.cpp:696 #3 0x2ab720e6c1fa in QDialog::~QDialog() qdialog.cpp:357 #4 0x2ab720e2b276 in QColorDialog::~QColorDialog() qcolordialog.cpp:2187 #5 0x2ab720e5e2c6 in QColorDialog::getColor(QColor const&, QWidget*, QString const&, QFlags) qcolordialog.cpp:2148 #6 0x2ab720e5e473 in QColorDialog::getRgba(unsigned int, bool*, QWidget*) qcolordialog.cpp:2176 #7 0x407180 in tst_QColorDialog::testGetRgba() tst_qcolordialog.cpp:118 qfiledialog_p.h:112:5: runtime error: downcast of address 0x7ffd6858cc60 which does not point to an object of type 'QFileDialog' 0x7ffd6858cc60: note: object is of type 'QDialog' a1 2b 00 00 d8 1e 5e 0c a1 2b 00 00 b0 af 01 20 a1 2b 00 00 b0 20 5e 0c a1 2b 00 00 00 00 46 00 ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'QDialog' #0 0x2ba10980a9e7 in QFileDialogPrivate::q_func() const qfiledialog_p.h:112 #1 0x2ba10980a9e7 in QFileDialogPrivate::canBeNativeDialog() const qfiledialog.cpp:695 #2 0x2ba1097efe36 in QDialog::setVisible(bool) qdialog.cpp:696 #3 0x2ba1097d715a in QDialog::~QDialog() qdialog.cpp:357 #4 0x2ba109854c4b in QFileDialog::~QFileDialog() qfiledialog.cpp:380 #5 0x4179dc in tst_QFiledialog::init() tst_qfiledialog.cpp:175 Fix by replacing Q_Q with the the equivalent expression for QDialog. We can't re-use QDialogPrivate::q_func() here, since that is private, and probably should stay like that. Also fix an invalid member call in QColorDialogPrivate::canBeNativeDialog(): qcolordialog.cpp:2050:5: runtime error: member call on address 0x7ffdf50c1ec0 which does not point to an object of type 'QColorDialog' 0x7ffdf50c1ec0: note: object is of type 'QDialog' fd 7f 00 00 d8 6e c7 23 b7 2a 00 00 50 c1 af 01 00 00 00 00 b0 70 c7 23 b7 2a 00 00 00 00 1a 1e ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'QDialog' #0 0x2ab720e4e5ea in QColorDialog::options() const qcolordialog.cpp:2050 #1 0x2ab720e4e8c8 in QColorDialogPrivate::canBeNativeDialog() const qcolordialog.cpp:1870 #2 0x2ab720e84ed6 in QDialog::setVisible(bool) qdialog.cpp:696 #3 0x2ab720e6c1fa in QDialog::~QDialog() qdialog.cpp:357 #4 0x2ab720e2b276 in QColorDialog::~QColorDialog() qcolordialog.cpp:2187 #5 0x2ab720e5e2c6 in QColorDialog::getColor(QColor const&, QWidget*, QString const&, QFlags) qcolordialog.cpp:2148 #6 0x2ab720e5e473 in QColorDialog::getRgba(unsigned int, bool*, QWidget*) qcolordialog.cpp:2176 #7 0x407180 in tst_QColorDialog::testGetRgba() tst_qcolordialog.cpp:118 by accessing the data member directly instead of through the Public API. Fix the same code in QFileDialog, even though the autotest coverage is too limited for UBSan to point that one out explicitly. This commit amends abe8b4ab9b5243b477c72f3e900d4f6cca79b5c5, in which it should have been included in the first place... Change-Id: Iff0538eba61d2381359f0b61f35918d643f7aa0c Reviewed-by: Thiago Macieira --- src/widgets/dialogs/qcolordialog.cpp | 6 ++++-- src/widgets/dialogs/qfiledialog.cpp | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp index c4cc21cbe5..8e699e87c5 100644 --- a/src/widgets/dialogs/qcolordialog.cpp +++ b/src/widgets/dialogs/qcolordialog.cpp @@ -1862,12 +1862,14 @@ void QColorDialogPrivate::retranslateStrings() bool QColorDialogPrivate::canBeNativeDialog() const { - Q_Q(const QColorDialog); + // Don't use Q_Q here! This function is called from ~QDialog, + // so Q_Q calling q_func() invokes undefined behavior (invalid cast in q_func()). + const QDialog * const q = static_cast(q_ptr); if (nativeDialogInUse) return true; if (q->testAttribute(Qt::WA_DontShowOnScreen)) return false; - if (q->options() & QColorDialog::DontUseNativeDialog) + if (options->options() & QColorDialog::DontUseNativeDialog) return false; QLatin1String staticName(QColorDialog::staticMetaObject.className()); diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index bc2de899f5..3aa9052917 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -695,12 +695,14 @@ void QFileDialogPrivate::emitFilesSelected(const QStringList &files) bool QFileDialogPrivate::canBeNativeDialog() const { - Q_Q(const QFileDialog); + // Don't use Q_Q here! This function is called from ~QDialog, + // so Q_Q calling q_func() invokes undefined behavior (invalid cast in q_func()). + const QDialog * const q = static_cast(q_ptr); if (nativeDialogInUse) return true; if (q->testAttribute(Qt::WA_DontShowOnScreen)) return false; - if (q->options() & QFileDialog::DontUseNativeDialog) + if (options->options() & QFileDialog::DontUseNativeDialog) return false; QLatin1String staticName(QFileDialog::staticMetaObject.className()); -- cgit v1.2.3 From 8e45fe6d6c2084752983d905cf22f777e7062baf Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 21 Sep 2016 09:12:24 +0200 Subject: QGraphicsScene: don't search for nullptr Following f6cb8b1af8f15a06898c5c71f81c64779d9478f6, take advantage of the nullptr return case of QGraphicsItem ::toGraphicsObject() by not looking up nullptr in the QList and the two QHashes. They don't contain nullptrs. Change-Id: Ic1cfbb4c60061577a09348ef78fdc573f95ad9a8 Reviewed-by: Friedemann Kleint --- src/widgets/graphicsview/qgraphicsscene.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp index ebc521eb00..5e3b426d49 100644 --- a/src/widgets/graphicsview/qgraphicsscene.cpp +++ b/src/widgets/graphicsview/qgraphicsscene.cpp @@ -710,10 +710,11 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item) ++it; } - QGraphicsObject *dummy = item->toGraphicsObject(); - cachedTargetItems.removeOne(dummy); - cachedItemGestures.remove(dummy); - cachedAlreadyDeliveredGestures.remove(dummy); + if (QGraphicsObject *dummy = item->toGraphicsObject()) { + cachedTargetItems.removeOne(dummy); + cachedItemGestures.remove(dummy); + cachedAlreadyDeliveredGestures.remove(dummy); + } foreach (Qt::GestureType gesture, item->d_ptr->gestureContext.keys()) ungrabGesture(item, gesture); -- cgit v1.2.3 From 8cd28ea8850c5365c47dd65de16f528e2e223835 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Thu, 15 Sep 2016 14:07:07 +0200 Subject: QGuiApplication, platform plugins: don't modify AA_DontUseNativeMenuBar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The default should be false, meaning the application will prefer to use a native menubar if the platform supports it. The application author can set it to true if he wants to always use a Qt-rendered menubar instead; or, he can call QMenuBar::setNativeMenuBar(). Qt and its plugins should not override the author's wishes. Instead, if the platform plugin cannot create a native menubar for whatever reason, createPlatformMenuBar() will return null, and QMenuBar will fall back to using a Qt menubar instead. The application can check the result via QMenuBar::isNativeMenuBar(). QMdiArea when maximized inside a QMainWindow with an empty title does not replace the main window's title if we are using native menus. This behavior turned out to be the same on Unity as it is on macOS, so the autotest needed adjustment to expect that behavior whenever the menubar is native, not only on certain platforms. tst_QMenuBar::allowActiveAndDisabled() tests a standalone QMenuBar. In f92f78094 it was disabled on macOS, but on Ubuntu it passes as long as we force it to be a non-native menubar, so it should pass that way on macOS too. Removed unused variable RESET to fix warning. Task-number: QTBUG-54793 Change-Id: I716e40da709f96331cbbf25213bd7bc153e4dbe2 Reviewed-by: Morten Johan Sørvig --- src/gui/kernel/qguiapplication.cpp | 6 ------ src/plugins/platforms/android/qandroidplatformtheme.cpp | 3 --- src/plugins/platforms/cocoa/qcocoaintegration.mm | 2 -- 3 files changed, 11 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index f60cfd8af3..353b623a3b 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1192,12 +1192,6 @@ static void init_plugins(const QList &pluginList) void QGuiApplicationPrivate::createPlatformIntegration() { - // Use the Qt menus by default. Platform plugins that - // want to enable a native menu implementation can clear - // this flag. - QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, true); - - QHighDpiScaling::initHighDpiScaling(); // Load the platform integration diff --git a/src/plugins/platforms/android/qandroidplatformtheme.cpp b/src/plugins/platforms/android/qandroidplatformtheme.cpp index 3949113240..f8d0b9c8ba 100644 --- a/src/plugins/platforms/android/qandroidplatformtheme.cpp +++ b/src/plugins/platforms/android/qandroidplatformtheme.cpp @@ -368,9 +368,6 @@ QAndroidPlatformTheme::QAndroidPlatformTheme(QAndroidPlatformNativeInterface *an // default in case the style has not set a font m_systemFont = QFont(QLatin1String("Roboto"), 14.0 * 100 / 72); // keep default size the same after changing from 100 dpi to 72 dpi - - // by default use native menu bar - QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, false); } QPlatformMenuBar *QAndroidPlatformTheme::createPlatformMenuBar() const diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index f02dad675e..e481cede17 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -300,8 +300,6 @@ QCocoaIntegration::QCocoaIntegration(const QStringList ¶mList) initResources(); QMacAutoReleasePool pool; - qApp->setAttribute(Qt::AA_DontUseNativeMenuBar, false); - NSApplication *cocoaApplication = [QNSApplication sharedApplication]; qt_redirectNSApplicationSendEvent(); -- cgit v1.2.3 From b4995eb7491c1b4784a1bf48db834c11c42b8d9d Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 26 Sep 2016 23:41:41 +0200 Subject: QStackedLayout: Fix UB (invalid cast) in qt_wasDeleted() Found by UBSan: qstackedlayout.cpp:261:98: runtime error: downcast of address 0x60400003cd10 which does not point to an object of type 'QtFriendlyLayoutWidget' 0x60400003cd10: note: object is of type 'QWidget' 0e 00 80 76 70 0b 06 3f d6 2a 00 00 00 99 00 00 50 61 00 00 20 0d 06 3f d6 2a 00 00 00 00 be be ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'QWidget' #0 0x2ad637b8f58f in qt_wasDeleted qstackedlayout.cpp:261 #1 0x2ad637b8f58f in QStackedLayout::takeAt(int) qstackedlayout.cpp:285 #2 0x2ad637b4afcb in QLayout::removeWidget(QWidget*) qlayout.cpp:1369 #3 0x413534 in tst_QStackedLayout::testCase() tst_qstackedlayout.cpp:155 Caused by using a struct to get access to QWidgetPrivate::wasDeleted using a cast. That cast is invalid, of course, so simply use QWidgetPrivate::get(). Caveat: we need a const version of that function, but that didn't exist, yet, so added one. Change-Id: I27d449b90be7e2072646d950c676b500ef698349 Reviewed-by: Thiago Macieira --- src/widgets/kernel/qstackedlayout.cpp | 12 ++++-------- src/widgets/kernel/qwidget_p.h | 1 + 2 files changed, 5 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/widgets/kernel/qstackedlayout.cpp b/src/widgets/kernel/qstackedlayout.cpp index 029c2bcec2..7afd6d076d 100644 --- a/src/widgets/kernel/qstackedlayout.cpp +++ b/src/widgets/kernel/qstackedlayout.cpp @@ -35,7 +35,7 @@ #include "qlayout_p.h" #include -#include +#include "private/qwidget_p.h" #include "private/qlayoutengine_p.h" QT_BEGIN_NAMESPACE @@ -245,14 +245,10 @@ QLayoutItem *QStackedLayout::itemAt(int index) const // Code that enables proper handling of the case that takeAt() is // called somewhere inside QObject destructor (can't call hide() // on the object then) - -class QtFriendlyLayoutWidget : public QWidget +static bool qt_wasDeleted(const QWidget *w) { -public: - inline bool wasDeleted() const { return d_ptr->wasDeleted; } -}; - -static bool qt_wasDeleted(const QWidget *w) { return static_cast(w)->wasDeleted(); } + return QWidgetPrivate::get(w)->wasDeleted; +} /*! diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index 5f07a8802a..37f2c0e5c7 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -323,6 +323,7 @@ public: ~QWidgetPrivate(); static QWidgetPrivate *get(QWidget *w) { return w->d_func(); } + static const QWidgetPrivate *get(const QWidget *w) { return w->d_func(); } QWExtra *extraData() const; QTLWExtra *topData() const; -- cgit v1.2.3 From fcf4767bffd201a0b8da1ed6f5425e3f5ce0e4ff Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 26 Sep 2016 19:56:07 +0200 Subject: QLayout: Fix UB (invalid cast) in widgetEvent() Found by UBSan: qlayout.cpp:612:50: runtime error: downcast of address 0x7ffcd4c39a70 which does not point to an object of type 'QWidget' 0x7ffcd4c39a70: note: object is of type 'QObject' 00 00 00 00 b0 43 4c 7b f5 2a 00 00 70 c9 28 02 00 00 00 00 08 93 9a 77 f5 2a 00 00 00 00 c3 d4 ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'QObject' #0 0x2af56f189960 in QLayout::widgetEvent(QEvent*) qlayout.cpp:612 #1 0x2af56f037660 in QApplicationPrivate::notify_helper(QObject*, QEvent*) qapplication.cpp:3732 #2 0x2af56f06ae5b in QApplication::notify(QObject*, QEvent*) qapplication.cpp:3704 #3 0x2af57989e383 in QCoreApplication::notifyInternal2(QObject*, QEvent*) qcoreapplication.cpp:988 #4 0x2af5799c1696 in QCoreApplication::sendEvent(QObject*, QEvent*) qcoreapplication.h:231 #5 0x2af5799c1696 in QObjectPrivate::setParent_helper(QObject*) qobject.cpp:2043 #6 0x2af5799c4823 in QObject::~QObject() qobject.cpp:1095 #7 0x2af56f2d205d in QWidget::~QWidget() qwidget.cpp:1549 #8 0x2af56f9c1366 in QFrame::~QFrame() qframe.cpp:262 #9 0x2af56f9e76cb in QLabel::~QLabel() qlabel.cpp:247 #10 0x458077 in tst_QStyleSheetStyle::emptyStyleSheet() tst_qstylesheetstyle.cpp:1400 Fix by not casting at all (or, to be precise, casting implicitly up instead of explicitly down). Change-Id: Ic19fd29e0cabd1aee5b1c93ca4c0fc70bc7a5927 Reviewed-by: Thiago Macieira --- src/widgets/kernel/qlayout.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/widgets/kernel/qlayout.cpp b/src/widgets/kernel/qlayout.cpp index 8631149f3d..7ca8de6f7a 100644 --- a/src/widgets/kernel/qlayout.cpp +++ b/src/widgets/kernel/qlayout.cpp @@ -540,7 +540,7 @@ void QLayout::invalidate() update(); } -static bool removeWidgetRecursively(QLayoutItem *li, QWidget *w) +static bool removeWidgetRecursively(QLayoutItem *li, QObject *w) { QLayout *lay = li->layout(); if (!lay) @@ -603,12 +603,11 @@ void QLayout::widgetEvent(QEvent *e) { QChildEvent *c = (QChildEvent *)e; if (c->child()->isWidgetType()) { - QWidget *w = (QWidget *)c->child(); #ifndef QT_NO_MENUBAR - if (w == d->menubar) + if (c->child() == d->menubar) d->menubar = 0; #endif - removeWidgetRecursively(this, w); + removeWidgetRecursively(this, c->child()); } } break; -- cgit v1.2.3 From 6af82fe9fd19361f56ea4bf5a6be371722bafde3 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 20 Sep 2016 13:58:18 +0200 Subject: Windows: Fix crash when loading color fonts from data When color fonts are loaded from data, the font returned will be a DirectWrite engine even the hinting preference does not require it. This would cause a crash as we unconditionally cast the pointer to QWindowsFontEngine*. Using GDI and the unique family name hack to load the font from data works fine, but we need to make sure we reference count the font resource in this case, so we have to implement the setUniqueFamilyName() logic in the DirectWrite engine as well for this specific case. [ChangeLog][Windows] Fixed crash when loading color fonts from data. Task-number: QTBUG-55595 Change-Id: I05443e8a396105da68ac4872b48339130b86c7f6 Reviewed-by: Friedemann Kleint Reviewed-by: Lars Knoll --- .../platforms/windows/qwindowsfontdatabase.cpp | 19 +++++++++++++++++-- .../windows/qwindowsfontenginedirectwrite.cpp | 18 +++++++++++++++--- .../platforms/windows/qwindowsfontenginedirectwrite.h | 3 +++ 3 files changed, 35 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp index 314da702eb..bc237bc88c 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp @@ -1231,8 +1231,23 @@ QT_WARNING_POP Q_ASSERT(fontEngine->ref.load() == 0); // Override the generated font name - static_cast(fontEngine)->setUniqueFamilyName(uniqueFamilyName); - fontEngine->fontDef.family = actualFontName; + switch (fontEngine->type()) { + case QFontEngine::Win: + static_cast(fontEngine)->setUniqueFamilyName(uniqueFamilyName); + fontEngine->fontDef.family = actualFontName; + break; + +#if !defined(QT_NO_DIRECTWRITE) + case QFontEngine::DirectWrite: + static_cast(fontEngine)->setUniqueFamilyName(uniqueFamilyName); + fontEngine->fontDef.family = actualFontName; + break; +#endif // !QT_NO_DIRECTWRITE + + default: + Q_ASSERT_X(false, Q_FUNC_INFO, "Unhandled font engine."); + } + UniqueFontData uniqueData; uniqueData.handle = fontHandle; uniqueData.refCount.ref(); diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp index 49eb7cfdec..0fdd4615f6 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp @@ -48,6 +48,8 @@ #include #include #include +#include +#include #if defined(QT_USE_DIRECTWRITE2) # include @@ -233,6 +235,11 @@ QWindowsFontEngineDirectWrite::~QWindowsFontEngineDirectWrite() if (m_directWriteBitmapRenderTarget != 0) m_directWriteBitmapRenderTarget->Release(); + + if (!m_uniqueFamilyName.isEmpty()) { + QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase(); + static_cast(pfdb)->derefUniqueFont(m_uniqueFamilyName); + } } void QWindowsFontEngineDirectWrite::collectMetrics() @@ -765,12 +772,17 @@ QImage QWindowsFontEngineDirectWrite::alphaRGBMapForGlyph(glyph_t t, QFontEngine *QWindowsFontEngineDirectWrite::cloneWithSize(qreal pixelSize) const { - QFontEngine *fontEngine = new QWindowsFontEngineDirectWrite(m_directWriteFontFace, - pixelSize, - m_fontEngineData); + QWindowsFontEngineDirectWrite *fontEngine = new QWindowsFontEngineDirectWrite(m_directWriteFontFace, + pixelSize, + m_fontEngineData); fontEngine->fontDef = fontDef; fontEngine->fontDef.pixelSize = pixelSize; + if (!m_uniqueFamilyName.isEmpty()) { + fontEngine->setUniqueFamilyName(m_uniqueFamilyName); + QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase(); + static_cast(pfdb)->refUniqueFont(m_uniqueFamilyName); + } return fontEngine; } diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h index f038dcfde4..37e511ce3e 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h @@ -108,6 +108,8 @@ public: IDWriteFontFace *directWriteFontFace() const { return m_directWriteFontFace; } + void setUniqueFamilyName(const QString &newName) { m_uniqueFamilyName = newName; } + private: QImage imageForGlyph(glyph_t t, QFixed subPixelPosition, int margin, const QTransform &xform); void collectMetrics(); @@ -126,6 +128,7 @@ private: QFixed m_xHeight; QFixed m_lineGap; FaceId m_faceId; + QString m_uniqueFamilyName; }; QT_END_NAMESPACE -- cgit v1.2.3 From 158781ff2555fabcb9af6b47c887519ade5aba50 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Tue, 6 Sep 2016 12:36:55 +0200 Subject: QSslSocket: respect read buffer's max size (SecureTransport) 1. QSslSocketBackendPrivate::transmit was ignoring 'readBufferMaxSize'; as a result, we can have a user trying to set read buffer's size to a small value (and more important - reading slowly in a small chunks from this socket), but SSL itself socket reading 'too fast', potentially growing its internal buffer to a huge size. This also results in auto-tests failing - whenever we're trying to limit read rate in some test. 2. Update qsslsocket auto-test. Task-number: QTBUG-43388 Task-number: QTBUG-55170 Change-Id: Iedece26df0ac5b3b7cad62cc8c98aedc28e7ca5b Reviewed-by: Richard J. Moore --- src/network/ssl/qsslsocket_mac.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/network/ssl/qsslsocket_mac.cpp b/src/network/ssl/qsslsocket_mac.cpp index 8aa9269f4b..233f7b5d15 100644 --- a/src/network/ssl/qsslsocket_mac.cpp +++ b/src/network/ssl/qsslsocket_mac.cpp @@ -668,7 +668,7 @@ void QSslSocketBackendPrivate::transmit() if (connectionEncrypted) { QVarLengthArray data; - while (context) { + while (context && (!readBufferMaxSize || buffer.size() < readBufferMaxSize)) { size_t readBytes = 0; data.resize(4096); const OSStatus err = SSLRead(context, data.data(), data.size(), &readBytes); -- cgit v1.2.3 From a95d103bd2ed907b11c483c91e32139144828148 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 20 Sep 2016 16:12:35 +0200 Subject: Add GLSL version 110 on Intel with compat profiles The Windows Intel drivers reject shader sources without a version directive in 3.2+ compatibility profiles. This is odd but can be worked around by adding #version 110 (which should be the default...) Change-Id: I1ccac41b80121e6423d4f8964d03dda52a433296 Task-number: QTBUG-55733 Reviewed-by: Friedemann Kleint Reviewed-by: Giuseppe D'Angelo Reviewed-by: Andy Nichols --- src/gui/opengl/qopenglshaderprogram.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/gui/opengl/qopenglshaderprogram.cpp b/src/gui/opengl/qopenglshaderprogram.cpp index d567800fbd..824831ab29 100644 --- a/src/gui/opengl/qopenglshaderprogram.cpp +++ b/src/gui/opengl/qopenglshaderprogram.cpp @@ -516,16 +516,26 @@ bool QOpenGLShader::compileSourceCode(const char *source) QVarLengthArray sourceChunks; QVarLengthArray sourceChunkLengths; + QOpenGLContext *ctx = QOpenGLContext::currentContext(); if (versionDirectivePosition.hasPosition()) { - // Append source up to #version directive + // Append source up to and including the #version directive sourceChunks.append(source); sourceChunkLengths.append(GLint(versionDirectivePosition.position)); + } else { + // QTBUG-55733: Intel on Windows with Compatibility profile requires a #version always + if (ctx->format().profile() == QSurfaceFormat::CompatibilityProfile) { + const char *vendor = reinterpret_cast(ctx->functions()->glGetString(GL_VENDOR)); + if (vendor && !strcmp(vendor, "Intel")) { + static const char version110[] = "#version 110\n"; + sourceChunks.append(version110); + sourceChunkLengths.append(GLint(sizeof(version110)) - 1); + } + } } // The precision qualifiers are useful on OpenGL/ES systems, // but usually not present on desktop systems. - QOpenGLContext *ctx = QOpenGLContext::currentContext(); const QSurfaceFormat currentSurfaceFormat = ctx->format(); QOpenGLContextPrivate *ctx_d = QOpenGLContextPrivate::get(QOpenGLContext::currentContext()); if (currentSurfaceFormat.renderableType() == QSurfaceFormat::OpenGL -- cgit v1.2.3 From 3379ace11b30d8e9a2c9b45789561ac44bf29c06 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Thu, 4 Aug 2016 16:41:12 +0200 Subject: QDateTimeEdit: synchronize time-spec before initializing display QDateTimeEdit ignores the time-spec of its date-time value, using its own time-spec instead; mostly, this works because it first conforms the value to its own time-spec. However, during construction, before doing this, it set up its display data, which could leave it with a different time (rather than a different representation of the given time) than it was asked to use. Moved the updateTimeSpec() calls to immediately after setting value in QDateTimeEditPrivate::init() to ensure correct handling. Added test. Task-number: QTBUG-54781 Change-Id: I3b07c10997abb858fc0b40558bff96e3fdabbd83 Reviewed-by: Jesus Fernandez Reviewed-by: Marc Mutz --- src/widgets/widgets/qdatetimeedit.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/widgets/qdatetimeedit.cpp b/src/widgets/widgets/qdatetimeedit.cpp index 960f84c13a..96a37197e9 100644 --- a/src/widgets/widgets/qdatetimeedit.cpp +++ b/src/widgets/widgets/qdatetimeedit.cpp @@ -2388,18 +2388,21 @@ void QDateTimeEditPrivate::init(const QVariant &var) switch (var.type()) { case QVariant::Date: value = QDateTime(var.toDate(), QDATETIMEEDIT_TIME_MIN); + updateTimeSpec(); q->setDisplayFormat(defaultDateFormat); if (sectionNodes.isEmpty()) // ### safeguard for broken locale q->setDisplayFormat(QLatin1String("dd/MM/yyyy")); break; case QVariant::DateTime: value = var; + updateTimeSpec(); q->setDisplayFormat(defaultDateTimeFormat); if (sectionNodes.isEmpty()) // ### safeguard for broken locale q->setDisplayFormat(QLatin1String("dd/MM/yyyy hh:mm:ss")); break; case QVariant::Time: value = QDateTime(QDATETIMEEDIT_DATE_INITIAL, var.toTime()); + updateTimeSpec(); q->setDisplayFormat(defaultTimeFormat); if (sectionNodes.isEmpty()) // ### safeguard for broken locale q->setDisplayFormat(QLatin1String("hh:mm:ss")); @@ -2412,7 +2415,6 @@ void QDateTimeEditPrivate::init(const QVariant &var) if (QApplication::keypadNavigationEnabled()) q->setCalendarPopup(true); #endif - updateTimeSpec(); q->setInputMethodHints(Qt::ImhPreferNumbers); setLayoutItemMargins(QStyle::SE_DateTimeEditLayoutItem); } -- cgit v1.2.3 From e3cbf0f1962958457f6e09fcfdc92d8cac4b6511 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Tue, 27 Sep 2016 09:13:12 +0200 Subject: Cocoa: Get mouse position from the event We want the coordinates for a mouse event to be the position at the time of event generation, not the current position. This is a followup to 39be577c which fixed this for some cases. This commit replaces all usages of [NSEvent mouseLocation] with code that gets the location from the event. Change-Id: I691a46a61ce65e2b33335453b5b22de01f76d767 Task-id: QTBUG-54399 Task-id: QTBUG-37926 Reviewed-by: Shawn Rutledge --- src/plugins/platforms/cocoa/qnsview.mm | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 0566541945..d29272a88f 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -1134,7 +1134,7 @@ QT_WARNING_POP QPointF windowPoint; QPointF screenPoint; - [self convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; + [self convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; m_platformWindow->m_enterLeaveTargetWindow = m_platformWindow->childWindowAt(windowPoint.toPoint()); QWindowSystemInterface::handleEnterEvent(m_platformWindow->m_enterLeaveTargetWindow, windowPoint, screenPoint); } @@ -1176,7 +1176,7 @@ Q_GLOBAL_STATIC(QCocoaTabletDeviceDataHash, tabletDeviceDataHash) QPointF windowPoint; QPointF screenPoint; - [self convertFromScreen:[NSEvent mouseLocation] toWindowPoint: &windowPoint andScreenPoint: &screenPoint]; + [self convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint: &windowPoint andScreenPoint: &screenPoint]; uint deviceId = [theEvent deviceID]; if (!tabletDeviceDataHash->contains(deviceId)) { @@ -1391,7 +1391,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) const NSTimeInterval timestamp = [event timestamp]; QPointF windowPoint; QPointF screenPoint; - [self convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; + [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; QWindowSystemInterface::handleGestureEventWithRealValue(m_window, timestamp, Qt::ZoomNativeGesture, [event magnification], windowPoint, screenPoint); } @@ -1404,7 +1404,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) const NSTimeInterval timestamp = [event timestamp]; QPointF windowPoint; QPointF screenPoint; - [self convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; + [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; QWindowSystemInterface::handleGestureEventWithRealValue(m_window, timestamp, Qt::SmartZoomNativeGesture, zoomIn ? 1.0f : 0.0f, windowPoint, screenPoint); zoomIn = !zoomIn; @@ -1419,7 +1419,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) const NSTimeInterval timestamp = [event timestamp]; QPointF windowPoint; QPointF screenPoint; - [self convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; + [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; QWindowSystemInterface::handleGestureEventWithRealValue(m_window, timestamp, Qt::RotateNativeGesture, -[event rotation], windowPoint, screenPoint); } @@ -1430,7 +1430,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) const NSTimeInterval timestamp = [event timestamp]; QPointF windowPoint; QPointF screenPoint; - [self convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; + [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; qreal angle = 0.0f; if ([event deltaX] == 1) @@ -1451,7 +1451,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) const NSTimeInterval timestamp = [event timestamp]; QPointF windowPoint; QPointF screenPoint; - [self convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; + [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; qCDebug(lcQpaGestures) << "beginGestureWithEvent @" << windowPoint; QWindowSystemInterface::handleGestureEvent(m_window, timestamp, Qt::BeginNativeGesture, windowPoint, screenPoint); @@ -1463,7 +1463,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) const NSTimeInterval timestamp = [event timestamp]; QPointF windowPoint; QPointF screenPoint; - [self convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; + [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; QWindowSystemInterface::handleGestureEvent(m_window, timestamp, Qt::EndNativeGesture, windowPoint, screenPoint); } @@ -1507,7 +1507,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) QPointF qt_windowPoint; QPointF qt_screenPoint; - [self convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&qt_windowPoint andScreenPoint:&qt_screenPoint]; + [self convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&qt_windowPoint andScreenPoint:&qt_screenPoint]; NSTimeInterval timestamp = [theEvent timestamp]; ulong qt_timestamp = timestamp * 1000; -- cgit v1.2.3 From b9e42067268bc80d126e82c4d892ffe33bb4c17a Mon Sep 17 00:00:00 2001 From: Palo Kisa Date: Mon, 26 Sep 2016 22:16:55 +0200 Subject: QGraphicsAnchorLayout: Fix invalid use of Q_AUTOTEST_EXPORT The Q_AUTOTEST_EXPORT is defined in all cases. So usage as #if defined(Q_AUTOTEST_EXPORT) was wrong. Change-Id: Ia1c1526ad08fdfa35ca773d7c62f8bbba39a6d38 Reviewed-by: Marc Mutz Reviewed-by: Oswald Buddenhagen --- src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp | 4 ++-- src/widgets/graphicsview/qgraphicsanchorlayout_p.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp b/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp index dac8e61645..8c27af1da5 100644 --- a/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp +++ b/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp @@ -2090,7 +2090,7 @@ QList getVariables(const QList &constraints) void QGraphicsAnchorLayoutPrivate::calculateGraphs( QGraphicsAnchorLayoutPrivate::Orientation orientation) { -#if defined(QT_DEBUG) || defined(Q_AUTOTEST_EXPORT) +#if defined(QT_DEBUG) || defined(QT_BUILD_INTERNAL) lastCalculationUsedSimplex[orientation] = false; #endif @@ -2254,7 +2254,7 @@ bool QGraphicsAnchorLayoutPrivate::calculateTrunk(Orientation orientation, const sizeHints[orientation][Qt::MaximumSize] = ad->sizeAtMaximum; } -#if defined(QT_DEBUG) || defined(Q_AUTOTEST_EXPORT) +#if defined(QT_DEBUG) || defined(QT_BUILD_INTERNAL) lastCalculationUsedSimplex[orientation] = needsSimplex; #endif diff --git a/src/widgets/graphicsview/qgraphicsanchorlayout_p.h b/src/widgets/graphicsview/qgraphicsanchorlayout_p.h index a5c7f1e2ce..4f8a106811 100644 --- a/src/widgets/graphicsview/qgraphicsanchorlayout_p.h +++ b/src/widgets/graphicsview/qgraphicsanchorlayout_p.h @@ -568,7 +568,7 @@ public: bool graphHasConflicts[2]; QSet m_floatItems[2]; -#if defined(QT_DEBUG) || defined(Q_AUTOTEST_EXPORT) +#if defined(QT_DEBUG) || defined(QT_BUILD_INTERNAL) bool lastCalculationUsedSimplex[2]; #endif -- cgit v1.2.3 From c65621b36208556556ffaad473b53a3782ad5fd6 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 27 Sep 2016 13:41:55 +0200 Subject: QWidget: Fix UB (invalid cast) in sendResizeEvents() Found by UBSan: qwidget.cpp:5228:62: runtime error: downcast of address 0x61b00003d480 which does not point to an object of type 'QWidget' 0x61b00003d480: note: object is of type 'QMainWindowLayout' bc 00 00 75 90 2e 2a 78 4f 2b 00 00 40 c1 02 00 f0 60 00 00 78 2f 2a 78 4f 2b 00 00 00 00 00 00 ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'QMainWindowLayout' #0 0x2b4f70efb1c2 in sendResizeEvents qwidget.cpp:5228 #1 0x2b4f70f65f7f in QWidget::grab(QRect const&) qwidget.cpp:5252 #2 0x6b1746 in tst_QWidget::render_task188133() tst_qwidget.cpp:6615 Fix by performing the cast only after the test for isWidgetType() has succeeded. Change-Id: I061a60ef35bcb5fbefb9bc7b84706c9dd5afd207 Reviewed-by: Thiago Macieira --- src/widgets/kernel/qwidget.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index b99fca6620..b2db4e1529 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -5201,8 +5201,10 @@ static void sendResizeEvents(QWidget *target) const QObjectList children = target->children(); for (int i = 0; i < children.size(); ++i) { + if (!children.at(i)->isWidgetType()) + continue; QWidget *child = static_cast(children.at(i)); - if (child->isWidgetType() && !child->isWindow() && child->testAttribute(Qt::WA_PendingResizeEvent)) + if (!child->isWindow() && child->testAttribute(Qt::WA_PendingResizeEvent)) sendResizeEvents(child); } } -- cgit v1.2.3 From 24314c73ae711fb9bd16626c41a09ddeee0a7001 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 27 Sep 2016 10:41:41 +0200 Subject: QTapAndHoldGestureRecognizer: Fix several UBs (invalid cast) in recognize() As found by UBSan: qstandardgestures.cpp:511:67: runtime error: downcast of address 0x7ffc9beb1b90 which does not point to an object of type 'QTouchEvent' 0x7ffc9beb1b90: note: object is of type 'QPlatformSurfaceEvent' fc 7f 00 00 08 93 b1 6f f5 2a 00 00 00 00 00 00 00 00 00 00 d9 00 ec 9b 00 00 00 00 49 01 c1 5e ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'QPlatformSurfaceEvent' #0 0x2af55edfa66a in QTapAndHoldGestureRecognizer::recognize(QGesture*, QObject*, QEvent*) qstandardgestures.cpp:511 #1 0x2af55ee3d9bb in QGestureManager::filterEventThroughContexts(QMultiMap const&, QEvent*) qgesturemanager.cpp:276 #2 0x2af55ee4565b in QGestureManager::filterEvent(QWidget*, QEvent*) qgesturemanager.cpp:512 #3 0x2af55ee53945 in QGestureManager::filterEvent(QObject*, QEvent*) qgesturemanager.cpp:556 #4 0x2af55ea1b83a in QApplication::notify(QObject*, QEvent*) qapplication.cpp:3053 #5 0x2af573949d0f in QCoreApplication::notifyInternal2(QObject*, QEvent*) qcoreapplication.cpp:988 #6 0x2af56982ff94 in QCoreApplication::sendEvent(QObject*, QEvent*) qcoreapplication.h:231 #7 0x2af56982ff94 in QWindowPrivate::create(bool) qwindow.cpp:435 #8 0x2af55ecd10fe in QWidgetPrivate::create_sys(unsigned long long, bool, bool) qwidget.cpp:1471 #9 0x2af55ecc770e in QWidget::create(unsigned long long, bool, bool) qwidget.cpp:1333 #10 0x2af55ed80618 in QWidget::setVisible(bool) qwidget.cpp:8156 #11 0x4feec4 in tst_QWidget::touchEventsForGesturePendingWidgets() tst_qwidget.cpp:9824 qstandardgestures.cpp:512:67: runtime error: downcast of address 0x7ffc9beb1b90 which does not point to an object of type 'QMouseEvent' 0x7ffc9beb1b90: note: object is of type 'QPlatformSurfaceEvent' fc 7f 00 00 08 93 b1 6f f5 2a 00 00 00 00 00 00 00 00 00 00 d9 00 ec 9b 00 00 00 00 49 01 c1 5e ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'QPlatformSurfaceEvent' #0 0x2af55edfaa19 in QTapAndHoldGestureRecognizer::recognize(QGesture*, QObject*, QEvent*) qstandardgestures.cpp:512 [... skipping common lines ...] qstandardgestures.cpp:514:95: runtime error: downcast of address 0x 0x7ffc9beb1b90: note: object is of type 'QPlatformSurfaceEvent' fc 7f 00 00 08 93 b1 6f f5 2a 00 00 00 00 00 00 00 00 00 00 d9 00 ec 9b 00 00 00 0 ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'QPlatformSurfaceEvent' #0 0x2af55edfa966 in QTapAndHoldGestureRecognizer::recognize(QGesture*, QObject*, QEvent*) qstandardgestures.cpp:514 [... skipping common lines ...] The problem is that the casts are done outside the switch that determines the event's type, so for any given event object, at least any two of the casts are invalid. This could actually be a real problem, because it's trivial for a compiler to prove that these three lines unconditionally invoke UB, so it has all the right in the world to decide to drop the complete rest of the function, using this line of reasoning: 1. The only way for these three casts not to be UB is if event == nullptr. 2. If event == nullptr, then event->type() invokes UB, so event cannot be nullptr. 3. The only way both can be true is if this code path is never taken. I can thus assume that object == state && event->type() == QEvent::Timer is always true, drop the check and execute the if block unconditionally (I need to call QEvent::type(), to satisfy the as-if-rule, but I needn't check its return value). Fix by moving the casts where they belong: into each case of the switch, where the type of the event has been checked to match the target type of the cast. Change-Id: I3aee8e213dc19d2f51636bcc5221cc92b3142e58 Reviewed-by: Thiago Macieira --- src/widgets/kernel/qstandardgestures.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/widgets/kernel/qstandardgestures.cpp b/src/widgets/kernel/qstandardgestures.cpp index d7589cc594..dd3f782120 100644 --- a/src/widgets/kernel/qstandardgestures.cpp +++ b/src/widgets/kernel/qstandardgestures.cpp @@ -502,45 +502,46 @@ QTapAndHoldGestureRecognizer::recognize(QGesture *state, QObject *object, return QGestureRecognizer::FinishGesture | QGestureRecognizer::ConsumeEventHint; } - const QTouchEvent *ev = static_cast(event); - const QMouseEvent *me = static_cast(event); -#ifndef QT_NO_GRAPHICSVIEW - const QGraphicsSceneMouseEvent *gsme = static_cast(event); -#endif - enum { TapRadius = 40 }; switch (event->type()) { #ifndef QT_NO_GRAPHICSVIEW - case QEvent::GraphicsSceneMousePress: + case QEvent::GraphicsSceneMousePress: { + const QGraphicsSceneMouseEvent *gsme = static_cast(event); d->position = gsme->screenPos(); q->setHotSpot(d->position); if (d->timerId) q->killTimer(d->timerId); d->timerId = q->startTimer(QTapAndHoldGesturePrivate::Timeout); return QGestureRecognizer::MayBeGesture; // we don't show a sign of life until the timeout + } #endif - case QEvent::MouseButtonPress: + case QEvent::MouseButtonPress: { + const QMouseEvent *me = static_cast(event); d->position = me->globalPos(); q->setHotSpot(d->position); if (d->timerId) q->killTimer(d->timerId); d->timerId = q->startTimer(QTapAndHoldGesturePrivate::Timeout); return QGestureRecognizer::MayBeGesture; // we don't show a sign of life until the timeout - case QEvent::TouchBegin: + } + case QEvent::TouchBegin: { + const QTouchEvent *ev = static_cast(event); d->position = ev->touchPoints().at(0).startScreenPos(); q->setHotSpot(d->position); if (d->timerId) q->killTimer(d->timerId); d->timerId = q->startTimer(QTapAndHoldGesturePrivate::Timeout); return QGestureRecognizer::MayBeGesture; // we don't show a sign of life until the timeout + } #ifndef QT_NO_GRAPHICSVIEW case QEvent::GraphicsSceneMouseRelease: #endif case QEvent::MouseButtonRelease: case QEvent::TouchEnd: return QGestureRecognizer::CancelGesture; // get out of the MayBeGesture state - case QEvent::TouchUpdate: + case QEvent::TouchUpdate: { + const QTouchEvent *ev = static_cast(event); if (d->timerId && ev->touchPoints().size() == 1) { QTouchEvent::TouchPoint p = ev->touchPoints().at(0); QPoint delta = p.pos().toPoint() - p.startPos().toPoint(); @@ -548,7 +549,9 @@ QTapAndHoldGestureRecognizer::recognize(QGesture *state, QObject *object, return QGestureRecognizer::MayBeGesture; } return QGestureRecognizer::CancelGesture; + } case QEvent::MouseMove: { + const QMouseEvent *me = static_cast(event); QPoint delta = me->globalPos() - d->position.toPoint(); if (d->timerId && delta.manhattanLength() <= TapRadius) return QGestureRecognizer::MayBeGesture; @@ -556,6 +559,7 @@ QTapAndHoldGestureRecognizer::recognize(QGesture *state, QObject *object, } #ifndef QT_NO_GRAPHICSVIEW case QEvent::GraphicsSceneMouseMove: { + const QGraphicsSceneMouseEvent *gsme = static_cast(event); QPoint delta = gsme->screenPos() - d->position.toPoint(); if (d->timerId && delta.manhattanLength() <= TapRadius) return QGestureRecognizer::MayBeGesture; -- cgit v1.2.3