QFileDialog: fix UB (invalid cast) in Private::setVisible()
The function can be called from ~QDialog(), in which case a cast of q_ptr to QFileDialog is UB. Says UBSan: qfiledialog_p.h:78:5: runtime error: downcast of address 0x7ffe7a8ad5a0 which does not point to an object of type 'QFileDialog' 0x7ffe7a8ad5a0: note: object is of type 'QDialog' fe 7f 00 00 30 44 d8 fb d2 7f 00 00 80 b4 00 00 90 61 00 00 08 46 d8 fb d2 7f 00 00 00 00 00 00 ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'QDialog' #0 0x7fd2f96d7587 in QFileDialogPrivate::q_func() qfiledialog_p.h:78 #1 0x7fd2f96d7587 in QFileDialogPrivate::setVisible(bool) qfiledialog.cpp:860 #2 0x7fd2f95465f5 in QDialog::setVisible(bool) qdialog.cpp:757 #3 0x7fd2f6d88768 in QWidget::hide() qwidget.cpp:8179 #4 0x7fd2f9545e09 in QDialog::~QDialog() qdialog.cpp:398 Fix by casting to QFileDialog only on show() (in createWidgets()), not hide(), and otherwise cast at most to QDialog* (QWidget* would actually have sufficed). 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: I4e206f7c36c03e8cb8a36001beae283628960073 Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
This commit is contained in:
parent
52d3cb8904
commit
a6743bd3c7
@ -857,7 +857,9 @@ void QFileDialog::setVisible(bool visible)
|
|||||||
*/
|
*/
|
||||||
void QFileDialogPrivate::setVisible(bool visible)
|
void QFileDialogPrivate::setVisible(bool visible)
|
||||||
{
|
{
|
||||||
Q_Q(QFileDialog);
|
// Don't use Q_Q here! This function is called from ~QDialog,
|
||||||
|
// so Q_Q calling q_func() invokes undefined behavior (invalid cast in q_func()).
|
||||||
|
const auto q = static_cast<QDialog *>(q_ptr);
|
||||||
|
|
||||||
if (canBeNativeDialog()){
|
if (canBeNativeDialog()){
|
||||||
if (setNativeDialogVisible(visible)){
|
if (setNativeDialogVisible(visible)){
|
||||||
@ -869,7 +871,7 @@ void QFileDialogPrivate::setVisible(bool visible)
|
|||||||
if (!nativeDialogInUse)
|
if (!nativeDialogInUse)
|
||||||
completer->setModel(nullptr);
|
completer->setModel(nullptr);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else if (visible) {
|
||||||
createWidgets();
|
createWidgets();
|
||||||
q->setAttribute(Qt::WA_DontShowOnScreen, false);
|
q->setAttribute(Qt::WA_DontShowOnScreen, false);
|
||||||
#if QT_CONFIG(fscompleter)
|
#if QT_CONFIG(fscompleter)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user