From 1b441c3941efc56f9b0ead35a4501056a74a77e1 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 7 Mar 2016 20:26:14 +0100 Subject: 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 --- src/widgets/kernel/qapplication.cpp | 9 +++++++-- src/widgets/kernel/qapplication_p.h | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index f7d4139ed8..b7de0d7a7e 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -562,13 +562,18 @@ QApplication::QApplication(int &argc, char **argv) QApplication::QApplication(int &argc, char **argv, int _internal) #endif : QGuiApplication(*new QApplicationPrivate(argc, argv, _internal)) -{ Q_D(QApplication); d->construct(); } +{ + Q_D(QApplication); + d->init(); +} /*! \internal */ -void QApplicationPrivate::construct() +void QApplicationPrivate::init() { + QGuiApplicationPrivate::init(); + initResources(); qt_is_gui_used = (application_type != QApplicationPrivate::Tty); diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h index cb158011f0..832d37a329 100644 --- a/src/widgets/kernel/qapplication_p.h +++ b/src/widgets/kernel/qapplication_p.h @@ -150,7 +150,7 @@ public: bool notify_helper(QObject *receiver, QEvent * e); - void construct( + void init( #ifdef Q_DEAD_CODE_FROM_QT4_X11 Display *dpy = 0, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0 #endif -- cgit v1.2.3