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 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 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 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