QMdiSubwindow: fix UB (invalid member call) in ControlContainer::removeButtonsFromMenuBar()

The function can be called from ~QMdiSubwindow(), and we checked for
QWidgetPrivate::data.in_destructor before proceeding with the removal
of buttons from the menubar, but we called
QPointer<QMdiSubwindow>::data()->window(), which, at this point in
time, had already been demoted to a QWidget:

Says UBSan:

  qpointer.h:75:14: runtime error: downcast of address 0x6040000aca10 which does not point to an object of type 'QMdiSubWindow'
   0x6040000aca10: note: object is of type 'QWidget'
    00 00 00 00  28 01 99 bc ff 7e 00 00  80 dc 0f 00 90 61 00 00  d8 02 99 bc ff 7e 00 00  00 00 be be
                 ^~~~~~~~~~~~~~~~~~~~~~~
                 vptr for 'QWidget'
       #0 0x7effb955f95a in QPointer<QMdiSubWindow>::data() const qpointer.h:75
       #1 0x7effb955f95a in QPointer<QMdiSubWindow>::operator->() const qpointer.h:79
       #2 0x7effb955f95a in QMdi::ControlContainer::removeButtonsFromMenuBar(QMenuBar*) qmdisubwindow.cpp:795
       #3 0x7effb9563031 in QMdi::ControlContainer::~ControlContainer() qmdisubwindow.cpp:717
       #4 0x7effb9566595 in QMdi::ControlContainer::~ControlContainer() qmdisubwindow.cpp:723
       #5 0x7eff8f4f2b7a in QObjectPrivate::deleteChildren() qobject.cpp:2226
       #6 0x7effb7bf732d in QWidget::~QWidget() qwidget.cpp:1557
       #7 0x7effb95cc02c in QMdiSubWindow::~QMdiSubWindow() qmdisubwindow.cpp:2254
       #8 0x7effb95cc1d5 in QMdiSubWindow::~QMdiSubWindow() qmdisubwindow.cpp:2254
       #9 0x7eff8f4f2b7a in QObjectPrivate::deleteChildren() qobject.cpp:2226
       #10 0x7effb7bf732d in QWidget::~QWidget() qwidget.cpp:1557
       #11 0x7effb7bffba5 in QWidget::~QWidget() qwidget.cpp:1584
       #12 0x7eff8f4f2b7a in QObjectPrivate::deleteChildren() qobject.cpp:2226
       #13 0x7effb7bf732d in QWidget::~QWidget() qwidget.cpp:1557
       #14 0x7effb85f0dc5 in QFrame::~QFrame() qframe.cpp:235
       #15 0x7effb859c747 in QAbstractScrollArea::~QAbstractScrollArea() qabstractscrollarea.cpp:478
       #16 0x7effb93c08a6 in QMdiArea::~QMdiArea() qmdiarea.cpp:1703
       #17 0x7effb93c0e55 in QMdiArea::~QMdiArea() qmdiarea.cpp:1703
       #18 0x7eff8f4f2b7a in QObjectPrivate::deleteChildren() qobject.cpp:2226
       #19 0x7effb7bf732d in QWidget::~QWidget() qwidget.cpp:1557
       #20 0x7effb920a425 in QMainWindow::~QMainWindow() qmainwindow.cpp:338

Fix by deleting the ControlContainer already from ~QMdiSubwindow(),
ie. when we have not yet been demoted to QWidget.

Amends the start of the public history.

Pick-to: 6.9 6.8 6.5 5.15
Change-Id: Ia43c857bc1842b2b4957cc79e00f790b045d8f94
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
Marc Mutz 2025-04-04 17:06:17 +02:00
parent 01ced9d45a
commit 2e3d39130c

View File

@ -2240,6 +2240,7 @@ QMdiSubWindow::~QMdiSubWindow()
d->removeButtonsFromMenuBar();
#endif
d->setActive(false);
delete d->controlContainer;
}
/*!