Test result of qobject_cast before dereferencing

Since QMainWindow::setMenuWidget accepts a QWidget (allowing users to
implement their own menu widget), we need to use qobject_cast on the
stored widget to see if it is a QMenuBar before calling QMenuBar APIs.

This qobject_cast may return nullptr.

Pick-to: 6.2
Fixes: QTBUG-98247
Change-Id: Iff1dbd24fa7ca09098fe49c179770356c966251d
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
bb10
Li Xi 2021-11-11 15:23:04 +08:00 committed by Volker Hilsheimer
parent 61aa482241
commit a0e7fbd4d5
2 changed files with 20 additions and 6 deletions

View File

@ -522,10 +522,10 @@ void QMainWindow::setMenuBar(QMenuBar *menuBar)
{
QLayout *topLayout = layout();
if (topLayout->menuBar() && topLayout->menuBar() != menuBar) {
if (QWidget *existingMenuBar = topLayout->menuBar(); existingMenuBar && existingMenuBar != menuBar) {
// Reparent corner widgets before we delete the old menu bar.
QMenuBar *oldMenuBar = qobject_cast<QMenuBar *>(topLayout->menuBar());
if (menuBar) {
QMenuBar *oldMenuBar = qobject_cast<QMenuBar *>(existingMenuBar);
if (oldMenuBar && menuBar) {
// TopLeftCorner widget.
QWidget *cornerWidget = oldMenuBar->cornerWidget(Qt::TopLeftCorner);
if (cornerWidget)
@ -535,9 +535,10 @@ void QMainWindow::setMenuBar(QMenuBar *menuBar)
if (cornerWidget)
menuBar->setCornerWidget(cornerWidget, Qt::TopRightCorner);
}
oldMenuBar->hide();
oldMenuBar->setParent(nullptr);
oldMenuBar->deleteLater();
existingMenuBar->hide();
existingMenuBar->setParent(nullptr);
existingMenuBar->deleteLater();
}
topLayout->setMenuBar(menuBar);
}

View File

@ -111,6 +111,7 @@ private slots:
void iconSize();
void toolButtonStyle();
void menuBar();
void customMenuBar();
void centralWidget();
void takeCentralWidget();
void corner();
@ -674,6 +675,18 @@ void tst_QMainWindow::menuBar()
}
}
// QTBUG-98247
void tst_QMainWindow::customMenuBar()
{
QMainWindow w;
std::unique_ptr<QWidget> menuWidget(new QWidget);
w.setMenuWidget(menuWidget.get());
QVERIFY(menuWidget->parentWidget());
QVERIFY(w.menuBar()); // implicitly calls setMenuBar
QVERIFY(!menuWidget->parentWidget());
menuWidget.reset();
}
#ifdef QT_BUILD_INTERNAL
void tst_QMainWindow::statusBar()
{