From d0aa81ee104107db1ce41a9bf0f91d4cb144f7de Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 26 Oct 2012 10:44:00 +0200 Subject: [PATCH] Fix a crash in QFileDialog when selecting an invalid name filter. When nameDetailsVisible is set to false and an invalid/empty string is passed to selectNameFilter(), the regexp used to strip the filter off the suffixes returns empty and a crash occurs. Change-Id: I926ea49514ff25a103977d8121fca1cf83d647f5 Reviewed-by: Miikka Heikkinen Reviewed-by: Sean Harmer --- src/widgets/dialogs/qfiledialog.cpp | 12 +++-- .../dialogs/qfiledialog/tst_qfiledialog.cpp | 47 ++++++++++++++++++- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index d9d318765d..2ff0d03c35 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -1201,9 +1201,11 @@ void QFileDialog::selectNameFilter(const QString &filter) d->selectNameFilter_sys(filter); return; } - int i; + int i = -1; if (testOption(HideNameFilterDetails)) { - i = d->qFileDialogUi->fileTypeCombo->findText(qt_strip_filters(qt_make_filter_list(filter)).first()); + const QStringList filters = qt_strip_filters(qt_make_filter_list(filter)); + if (!filters.isEmpty()) + i = d->qFileDialogUi->fileTypeCombo->findText(filters.first()); } else { i = d->qFileDialogUi->fileTypeCombo->findText(filter); } @@ -1770,7 +1772,7 @@ QString QFileDialog::getOpenFileName(QWidget *parent, // create a qt dialog QFileDialog dialog(args); - if (selectedFilter) + if (selectedFilter && !selectedFilter->isEmpty()) dialog.selectNameFilter(*selectedFilter); if (dialog.exec() == QDialog::Accepted) { if (selectedFilter) @@ -1855,7 +1857,7 @@ QStringList QFileDialog::getOpenFileNames(QWidget *parent, // create a qt dialog QFileDialog dialog(args); - if (selectedFilter) + if (selectedFilter && !selectedFilter->isEmpty()) dialog.selectNameFilter(*selectedFilter); if (dialog.exec() == QDialog::Accepted) { if (selectedFilter) @@ -1942,7 +1944,7 @@ QString QFileDialog::getSaveFileName(QWidget *parent, // create a qt dialog QFileDialog dialog(args); dialog.setAcceptMode(AcceptSave); - if (selectedFilter) + if (selectedFilter && !selectedFilter->isEmpty()) dialog.selectNameFilter(*selectedFilter); if (dialog.exec() == QDialog::Accepted) { if (selectedFilter) diff --git a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp index 32610fda18..8ce0742854 100644 --- a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp +++ b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp @@ -130,7 +130,9 @@ private slots: void selectFilter(); void viewMode(); void proxymodel(); + void setNameFilter_data(); void setNameFilter(); + void setEmptyNameFilter(); void focus(); void caption(); void historyBack(); @@ -1003,13 +1005,56 @@ void tst_QFiledialog::proxymodel() QCOMPARE(fd.proxyModel(), (QAbstractProxyModel*)0); } -void tst_QFiledialog::setNameFilter() +void tst_QFiledialog::setEmptyNameFilter() { QNonNativeFileDialog fd; fd.setNameFilter(QString()); fd.setNameFilters(QStringList()); } +void tst_QFiledialog::setNameFilter_data() +{ + QTest::addColumn("nameFilterDetailsVisible"); + QTest::addColumn("filters"); + QTest::addColumn("selectFilter"); + QTest::addColumn("expectedSelectedFilter"); + + QTest::newRow("namedetailsvisible-empty") << true << QStringList() << QString() << QString(); + QTest::newRow("namedetailsinvisible-empty") << false << QStringList() << QString() << QString(); + + const QString anyFileNoDetails = QLatin1String("Any files"); + const QString anyFile = anyFileNoDetails + QLatin1String(" (*)"); + const QString imageFilesNoDetails = QLatin1String("Image files"); + const QString imageFiles = imageFilesNoDetails + QLatin1String(" (*.png *.xpm *.jpg)"); + const QString textFileNoDetails = QLatin1String("Text files"); + const QString textFile = textFileNoDetails + QLatin1String(" (*.txt)"); + + QStringList filters; + filters << anyFile << imageFiles << textFile; + + QTest::newRow("namedetailsvisible-images") << true << filters << imageFiles << imageFiles; + QTest::newRow("namedetailsinvisible-images") << false << filters << imageFiles << imageFilesNoDetails; + + const QString invalid = "foo"; + QTest::newRow("namedetailsvisible-invalid") << true << filters << invalid << anyFile; + // Potential crash when trying to convert the invalid filter into a list and stripping it, resulting in an empty list. + QTest::newRow("namedetailsinvisible-invalid") << false << filters << invalid << anyFileNoDetails; +} + +void tst_QFiledialog::setNameFilter() +{ + QFETCH(bool, nameFilterDetailsVisible); + QFETCH(QStringList, filters); + QFETCH(QString, selectFilter); + QFETCH(QString, expectedSelectedFilter); + + QNonNativeFileDialog fd; + fd.setNameFilters(filters); + fd.setNameFilterDetailsVisible(nameFilterDetailsVisible); + fd.selectNameFilter(selectFilter); + QCOMPARE(fd.selectedNameFilter(), expectedSelectedFilter); +} + void tst_QFiledialog::focus() { QNonNativeFileDialog fd;