sc/inc/globstr.hrc | 1 + sc/source/ui/dataprovider/csvdataprovider.cxx | 23 ++++++++++++++++++++++- sc/source/ui/inc/dataprovider.hxx | 5 +++++ sc/source/ui/miscdlgs/dataproviderdlg.cxx | 16 +++++++++++++++- 4 files changed, 43 insertions(+), 2 deletions(-)
New commits: commit 6b5d160e836772e2ebb536da10329c1d29eb4a0b Author: Rafael Lima <[email protected]> AuthorDate: Tue Mar 11 19:20:51 2025 +0100 Commit: Mike Kaganski <[email protected]> CommitDate: Fri Mar 28 08:39:58 2025 +0100 tdf#165658 Data Provider: Catch exception when importing CSV Currently, the DataProvider parses the CSV in a separate thread. If an exception happens, LO crashes or freezes. With this patch, whenever a CSV parsing error happens, it gets caught and an error message is shown. Change-Id: Ia7e8facfe37f22d03647d94fcdf94ae0ecae10c1 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182791 Reviewed-by: Mike Kaganski <[email protected]> Tested-by: Jenkins diff --git a/sc/inc/globstr.hrc b/sc/inc/globstr.hrc index ceca2b5d31c7..c641672a7bbc 100644 --- a/sc/inc/globstr.hrc +++ b/sc/inc/globstr.hrc @@ -588,6 +588,7 @@ #define STR_SENSITIVITY_INCREASE NC_("STR_SENSITIVITY_INCREASE", "Allowable Increase") #define STR_SENSITIVITY_SHADOWPRICE NC_("STR_SENSITIVITY_SHADOWPRICE", "Shadow Price") #define STR_SENSITIVITY_RHS NC_("STR_SENSITIVITY_RHS", "Constraint R.H. Side") +#define STD_ERR_CSV_PARSE NC_("STD_ERR_CSV_PARSE", "An error occurred while parsing the CSV file.") #endif diff --git a/sc/source/ui/dataprovider/csvdataprovider.cxx b/sc/source/ui/dataprovider/csvdataprovider.cxx index 11051aab3f92..8c91aacf2ec5 100644 --- a/sc/source/ui/dataprovider/csvdataprovider.cxx +++ b/sc/source/ui/dataprovider/csvdataprovider.cxx @@ -10,6 +10,7 @@ #include <dataprovider.hxx> #include <datatransformation.hxx> #include <datamapper.hxx> +#include <exception> #include <stringutil.hxx> #include <tools/stream.hxx> @@ -72,6 +73,7 @@ CSVFetchThread::CSVFetchThread( , mbTerminate(false) , maDataTransformations(std::move(rDataTransformations)) , maImportFinishedHdl(std::move(aImportFinishedHdl)) + , mbIsParseError(false) { maConfig.delimiters.push_back(','); maConfig.text_qualifier = '"'; @@ -105,7 +107,18 @@ void CSVFetchThread::execute() CSVHandler aHdl(&mrDocument); orcus::csv_parser<CSVHandler> parser(aBuffer, aHdl, maConfig); - parser.parse(); + + try + { + parser.parse(); + } + catch(const orcus::parse_error&) + { + mbIsParseError = true; + mpLastException = std::current_exception(); + RequestTerminate(); + return; + } for (const auto& itr : maDataTransformations) { @@ -146,6 +159,14 @@ void CSVDataProvider::Import() { SolarMutexReleaser aReleaser; mxCSVFetchThread->join(); + + // tdf#165658 An exception may have happened during the parsing of the file. + // Since parsing happens in a separate thread, here we need to check if + // something wrong happened and then rethrow the exception + if (mxCSVFetchThread->IsParseError()) + { + std::rethrow_exception(mxCSVFetchThread->GetLastException()); + } } } diff --git a/sc/source/ui/inc/dataprovider.hxx b/sc/source/ui/inc/dataprovider.hxx index 4647c2ba4278..4234f8df2267 100644 --- a/sc/source/ui/inc/dataprovider.hxx +++ b/sc/source/ui/inc/dataprovider.hxx @@ -46,6 +46,9 @@ class CSVFetchThread : public salhelper::Thread std::function<void()> maImportFinishedHdl; + std::exception_ptr mpLastException; + bool mbIsParseError; + public: CSVFetchThread(ScDocument& rDoc, OUString , std::function<void()> aImportFinishedHdl, @@ -56,6 +59,8 @@ public: bool IsRequestedTerminate(); void Terminate(); void EndThread(); + bool IsParseError() { return mbIsParseError; } + auto GetLastException() { return mpLastException; } virtual void execute() override; }; diff --git a/sc/source/ui/miscdlgs/dataproviderdlg.cxx b/sc/source/ui/miscdlgs/dataproviderdlg.cxx index a7f60a98a6bd..7d4e851c48ab 100644 --- a/sc/source/ui/miscdlgs/dataproviderdlg.cxx +++ b/sc/source/ui/miscdlgs/dataproviderdlg.cxx @@ -8,6 +8,8 @@ */ #include <dataproviderdlg.hxx> +#include <scresid.hxx> +#include <globstr.hrc> #include <document.hxx> #include <dataprovider.hxx> @@ -1033,7 +1035,19 @@ void ScDataProviderDlg::import(ScDocument& rDoc, bool bInternal) return; rDoc.GetExternalDataMapper().insertDataSource(aSource); } - aSource.refresh(&rDoc, true); + + try + { + aSource.refresh(&rDoc, true); + } + catch(const orcus::parse_error&) + { + std::unique_ptr<weld::MessageDialog> xMsgBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Error, VclButtonsType::Close, + ScResId(STD_ERR_CSV_PARSE))); + xMsgBox->run(); + } + mxTable->Invalidate(); }
