diff options
author | Marc Mutz <[email protected]> | 2025-03-22 18:26:46 +0100 |
---|---|---|
committer | Marc Mutz <[email protected]> | 2025-03-25 05:33:51 +0000 |
commit | 8b4900bffff3386e108847c9e1ffe9a15e05e5d3 (patch) | |
tree | e30d26f25e8c75e37b866481e376e7f2823b7915 | |
parent | e72aea90fd82e81adac425e640cc9e8e6cd849cc (diff) |
QMessageBox: fix UB (invalid cast) in Private::setVisible()
The function can be called from ~QDialog(), in which case a cast of
q_ptr to QMessageBox is UB.
Says UBSan:
qmessagebox.cpp:182:5: runtime error: downcast of address 0x7ffdccfbda00 which does not point to an object of type 'QMessageBox'
0x7ffdccfbda00: note: object is of type 'QDialog'
88 7f 00 00 30 94 4a 73 88 7f 00 00 80 8c 00 00 90 61 00 00 08 96 4a 73 88 7f 00 00 00 00 fb cc
^~~~~~~~~~~~~~~~~~~~~~~
vptr for 'QDialog'
#0 0x7f8870f9a8a3 in QMessageBoxPrivate::q_func() qmessagebox.cpp:182
#1 0x7f8870f9a8a3 in QMessageBoxPrivate::setVisible(bool) qmessagebox.cpp:1660
#2 0x7f8870c6b3b5 in QDialog::setVisible(bool) qdialog.cpp:757
#3 0x7f886e4ad4b8 in QWidget::hide() qwidget.cpp:8179
#4 0x7f8870c6abc9 in QDialog::~QDialog() qdialog.cpp:398
Fix by casting to QMessageBox only on show(), not hide(), and
otherwise cast at most to QDialog* (QWidget* actually suffices).
Add a code comment.
Amends e0bb9e81ab1a9d71f2893844ea82430467422e21 (I think; it might
have been present in a different form before that).
Pick-to: 6.9 6.8 6.5
Change-Id: Ia163483c1998924a0d9c9fd589311af24a93d1fe
Reviewed-by: Axel Spoerl <[email protected]>
-rw-r--r-- | src/widgets/dialogs/qmessagebox.cpp | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/src/widgets/dialogs/qmessagebox.cpp b/src/widgets/dialogs/qmessagebox.cpp index df17399ca7e..f9d58e4d906 100644 --- a/src/widgets/dialogs/qmessagebox.cpp +++ b/src/widgets/dialogs/qmessagebox.cpp @@ -1657,12 +1657,15 @@ void QMessageBox::open(QObject *receiver, const char *member) void QMessageBoxPrivate::setVisible(bool visible) { - Q_Q(QMessageBox); - // Last minute setup - if (autoAddOkButton) - q->addButton(QMessageBox::Ok); - detectEscapeButton(); + if (visible) { + Q_Q(QMessageBox); + if (autoAddOkButton) + q->addButton(QMessageBox::Ok); + detectEscapeButton(); + } + // On hide, we may be called from ~QDialog(), so prevent accessing + // q_ptr as a QMessageBox! if (canBeNativeDialog()) setNativeDialogVisible(visible); @@ -1670,7 +1673,7 @@ void QMessageBoxPrivate::setVisible(bool visible) // Update WA_DontShowOnScreen based on whether the native dialog was shown, // so that QDialog::setVisible(visible) below updates the QWidget state correctly, // but skips showing the non-native version. - q->setAttribute(Qt::WA_DontShowOnScreen, nativeDialogInUse); + static_cast<QWidget*>(q_ptr)->setAttribute(Qt::WA_DontShowOnScreen, nativeDialogInUse); QDialogPrivate::setVisible(visible); } |