mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Bug 793467 - GnuCash crashes when trying to open a binary file instead of a CSV
The cause was an uncaught exception from boost::tokenizer. Fix and add test case.
This commit is contained in:
parent
6fe7d88548
commit
e71f561236
@ -717,7 +717,7 @@ CsvImpPriceAssist::file_confirm_cb ()
|
||||
catch (std::range_error &e)
|
||||
{
|
||||
/* Parsing failed ... */
|
||||
gnc_error_dialog (GTK_WINDOW(csv_imp_asst), "%s", e.what());
|
||||
gnc_error_dialog (GTK_WINDOW(csv_imp_asst), "%s", _(e.what()));
|
||||
return;
|
||||
}
|
||||
/* Get settings store and populate */
|
||||
|
@ -723,7 +723,7 @@ CsvImpTransAssist::file_confirm_cb ()
|
||||
catch (std::range_error &e)
|
||||
{
|
||||
/* Parsing failed ... */
|
||||
gnc_error_dialog (GTK_WINDOW (csv_imp_asst), "%s", e.what());
|
||||
gnc_error_dialog (GTK_WINDOW (csv_imp_asst), "%s", _(e.what()));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,10 @@
|
||||
#include <boost/locale.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
extern "C" {
|
||||
#include <glib/gi18n.h>
|
||||
}
|
||||
|
||||
void
|
||||
GncCsvTokenizer::set_separators(const std::string& separators)
|
||||
{
|
||||
@ -34,33 +38,40 @@ int GncCsvTokenizer::tokenize()
|
||||
m_tokenized_contents.clear();
|
||||
std::istringstream in_stream(m_utf8_contents);
|
||||
|
||||
while (std::getline (in_stream, buffer))
|
||||
try
|
||||
{
|
||||
// --- deal with line breaks in quoted strings
|
||||
buffer = boost::trim_copy (buffer); // Removes trailing newline and spaces
|
||||
last_quote = buffer.find_first_of('"');
|
||||
while (last_quote != std::string::npos)
|
||||
while (std::getline (in_stream, buffer))
|
||||
{
|
||||
if (last_quote == 0) // Test separately because last_quote - 1 would be out of range
|
||||
inside_quotes = !inside_quotes;
|
||||
else if (buffer[ last_quote - 1 ] != '\\')
|
||||
inside_quotes = !inside_quotes;
|
||||
// --- deal with line breaks in quoted strings
|
||||
buffer = boost::trim_copy (buffer); // Removes trailing newline and spaces
|
||||
last_quote = buffer.find_first_of('"');
|
||||
while (last_quote != std::string::npos)
|
||||
{
|
||||
if (last_quote == 0) // Test separately because last_quote - 1 would be out of range
|
||||
inside_quotes = !inside_quotes;
|
||||
else if (buffer[ last_quote - 1 ] != '\\')
|
||||
inside_quotes = !inside_quotes;
|
||||
|
||||
last_quote = buffer.find_first_of('"',last_quote+1);
|
||||
last_quote = buffer.find_first_of('"',last_quote+1);
|
||||
}
|
||||
|
||||
line.append(buffer);
|
||||
if (inside_quotes)
|
||||
{
|
||||
line.append(" ");
|
||||
continue;
|
||||
}
|
||||
// ---
|
||||
|
||||
Tokenizer tok(line, sep);
|
||||
vec.assign(tok.begin(),tok.end());
|
||||
m_tokenized_contents.push_back(vec);
|
||||
line.clear();
|
||||
}
|
||||
|
||||
line.append(buffer);
|
||||
if (inside_quotes)
|
||||
{
|
||||
line.append(" ");
|
||||
continue;
|
||||
}
|
||||
// ---
|
||||
|
||||
Tokenizer tok(line, sep);
|
||||
vec.assign(tok.begin(),tok.end());
|
||||
m_tokenized_contents.push_back(vec);
|
||||
line.clear();
|
||||
}
|
||||
catch (boost::escaped_list_error &e)
|
||||
{
|
||||
throw (std::range_error N_("There was an error parsing the file."));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -404,7 +404,7 @@ void GncTxImport::tokenize (bool guessColTypes)
|
||||
/* If it failed, generate an error. */
|
||||
if (m_parsed_lines.size() == 0)
|
||||
{
|
||||
throw (std::range_error ("Tokenizing failed."));
|
||||
throw (std::range_error (N_("There was an error parsing the file.")));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -138,6 +138,17 @@ TEST_F (GncTokenizerTest, tokenize_from_csv_file)
|
||||
* independently.
|
||||
*/
|
||||
|
||||
/* First test whether we're properly catching boost::tokenizer throws
|
||||
* This happens when the input data has invalid escape sequences */
|
||||
TEST_F (GncTokenizerTest, tokenize_binary_data)
|
||||
{
|
||||
GncCsvTokenizer *csvtok = dynamic_cast<GncCsvTokenizer*>(csv_tok.get());
|
||||
csvtok->set_separators (",");
|
||||
|
||||
set_utf8_contents (csv_tok, R"(\764Test,Something)");
|
||||
EXPECT_THROW (csv_tok->tokenize(), std::range_error);
|
||||
}
|
||||
|
||||
/* This helper function will run the parse step on the given data
|
||||
* with the parser as configured by the calling test function.
|
||||
* This allows the same code to be used with different csv test strings
|
||||
|
Loading…
Reference in New Issue
Block a user