summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@kdab.com>2016-03-07 20:26:14 +0100
committerMarc Mutz <marc.mutz@kdab.com>2016-03-09 07:42:50 +0000
commit1b441c3941efc56f9b0ead35a4501056a74a77e1 (patch)
treeba4ec7f678c9f91deaa1b3ba8a50aec07957ac45 /src/gui
parentfb7ef2b9f5cbc375fb35690326501be6a117314d (diff)
Q*Application: fix UB caused by accessing QGuiApplication from QCoreApplication ctor
As reported by ubsan: src/gui/kernel/qplatformintegration.cpp:463:10: runtime error: downcast of address 0x7ffdc2942490 which does not point to an object of type 'QGuiApplication' 0x7ffdc2942490: note: object is of type 'QCoreApplication' src/gui/kernel/qplatformintegration.cpp:466:14: runtime error: downcast of address 0x7ffdc2942490 which does not point to an object of type 'QGuiApplication' 0x7ffdc2942490: note: object is of type 'QCoreApplication' src/gui/kernel/qplatformintegration.cpp:466:43: runtime error: member call on address 0x7ffdc2942490 which does not point to an object of type 'QGuiApplication' 0x7ffdc2942490: note: object is of type 'QCoreApplication' to name just a few which are reported when running gui and widget auto-tests; there're definitely more where these came from. This is caused by QCoreApplication::init() being called from the QCoreApplication ctor, calling virtual functions on Q*AppPrivate, which happen to attempt, in this case, to emit QGuiApp signals. At that point in time, the QGuiApplication ctor has not entered the constructor body, ergo the object is still a QCoreApplication, and calling the signal, as a member function on the derived class, invokes UB. Fix by cleaning up the wild mix of initialization functions used in this hierarchy. The cleanup restores the 1. Q*ApplicationPrivate::Q*ApplicationPrivate() 2. Q*ApplicationPrivate::init(), calling each base class' init() as the first thing two-stage construction pattern commonly used elsewhere in Qt to make sure that the public class' object is fully constructed by the time each level's Private::init() is called. Change-Id: I290402b3232315d7ed687c97e740bfbdbd3ecd1a Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/kernel/qguiapplication.cpp4
-rw-r--r--src/gui/kernel/qguiapplication_p.h4
2 files changed, 5 insertions, 3 deletions
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 3808bec8a4..385264d70a 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -577,7 +577,7 @@ QGuiApplication::QGuiApplication(int &argc, char **argv, int flags)
QGuiApplication::QGuiApplication(QGuiApplicationPrivate &p)
: QCoreApplication(p)
{
- d_func()->init(); }
+}
/*!
Destructs the application.
@@ -1260,6 +1260,8 @@ void QGuiApplicationPrivate::eventDispatcherReady()
void QGuiApplicationPrivate::init()
{
+ QCoreApplicationPrivate::init();
+
QCoreApplicationPrivate::is_app_running = false; // Starting up.
bool loadTestability = false;
diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h
index 9c8b655c71..9e157aad51 100644
--- a/src/gui/kernel/qguiapplication_p.h
+++ b/src/gui/kernel/qguiapplication_p.h
@@ -75,6 +75,8 @@ public:
QGuiApplicationPrivate(int &argc, char **argv, int flags);
~QGuiApplicationPrivate();
+ void init();
+
void createPlatformIntegration();
void createEventDispatcher() Q_DECL_OVERRIDE;
void eventDispatcherReady() Q_DECL_OVERRIDE;
@@ -298,8 +300,6 @@ protected:
private:
friend class QDragManager;
- void init();
-
static QGuiApplicationPrivate *self;
static QTouchDevice *m_fakeTouchDevice;
static int m_fakeMouseSourcePointId;