summaryrefslogtreecommitdiffstats
path: root/src/widgets
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@kdab.com>2016-09-26 23:41:41 +0200
committerMarc Mutz <marc.mutz@kdab.com>2016-09-27 04:22:44 +0000
commitb4995eb7491c1b4784a1bf48db834c11c42b8d9d (patch)
tree65cd44837e7e316a05f3e6e5ef71bf355d22bc86 /src/widgets
parent6ea626a32fe070847629b6715c2a253717ff7412 (diff)
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 <thiago.macieira@intel.com>
Diffstat (limited to 'src/widgets')
-rw-r--r--src/widgets/kernel/qstackedlayout.cpp12
-rw-r--r--src/widgets/kernel/qwidget_p.h1
2 files changed, 5 insertions, 8 deletions
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 <qlist.h>
-#include <qwidget.h>
+#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<const QtFriendlyLayoutWidget*>(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;