QOpenGLWidget: Fix UB (invalid cast) in ~QOpenGLWidgetPrivate

The QOpenGLWidgetPrivate destructor calls reset(), which accesses
the Q-pointer. Calling Q_Q(Class) while still inside the private
class's destructor is wrong due to the cast in q_func() which is
undefined behavior at that stage.

Here is the UB report:
qopenglwidget.cpp:548:5: runtime error: downcast of address 0x000016d0e200 which does not point to an object of type 'QOpenGLWidget'
0x000016d0e200: note: object is of type 'QObject'
 00 00 00 00  10 30 32 0f 00 00 00 00  40 e2 d0 16 00 00 00 00  80 7b 42 0f 00 00 00 00  00 00 00 00
              ^~~~~~~~~~~~~~~~~~~~~~~
              vptr for 'QObject'

0     QOpenGLWidgetPrivate::reset    qopenglwidget.cpp    656    0x607e667
1     QOpenGLWidgetPrivate::~QOpenGLWidgetPrivate    qopenglwidget.cpp    570    0x60982ab
2     QOpenGLWidgetPrivate::~QOpenGLWidgetPrivate    qopenglwidget.cpp    569    0x6098516
3     QScopedPointerDeleter<QObjectData>::cleanup    qscopedpointer.h    54    0xcbf7058
4     QScopedPointer<QObjectData, QScopedPointerDeleter<QObjectData>>::~QScopedPointer    qscopedpointer.h    101    0xcbde858
5     QObject::~QObject    qobject.cpp    1042    0xcb94792
6     QWidget::~QWidget    qwidget.cpp    1701    0x5e173f7
7     QOpenGLWidget::~QOpenGLWidget    qopenglwidget.cpp    946    0x608d72b
8     ImagePreviewComponent::~ImagePreviewComponent    imagepreviewcomponent.h    16    0x58237b6
9     ImagePreviewComponent::~ImagePreviewComponent    imagepreviewcomponent.h    16    0x58238c6

Change-Id: If13932ac657afb9d1358ac82ab911a05e96cfbcd
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
This commit is contained in:
Dyami Caliri 2016-11-15 14:45:29 -08:00
parent 445191bba8
commit 32f8cbae90

View File

@ -572,11 +572,6 @@ public:
requestedFormat = QSurfaceFormat::defaultFormat();
}
~QOpenGLWidgetPrivate()
{
reset();
}
void reset();
void recreateFbo();
@ -962,7 +957,8 @@ QOpenGLWidget::QOpenGLWidget(QWidget *parent, Qt::WindowFlags f)
*/
QOpenGLWidget::~QOpenGLWidget()
{
makeCurrent();
Q_D(QOpenGLWidget);
d->reset();
}
/*!