Bug 406488 - crash importing a CSV
Summary: crash importing a CSV
Status: RESOLVED FIXED
Alias: None
Product: skrooge
Classification: Applications
Component: general (other bugs)
Version First Reported In: unspecified
Platform: Fedora RPMs Linux
: NOR crash
Target Milestone: 25.1.0
Assignee: Stephane MANKOWSKI
URL:
Keywords: drkonqi
Depends on:
Blocks:
 
Reported: 2019-04-13 00:36 UTC by skierpage
Modified: 2019-04-13 21:12 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed/Implemented In:
Sentry Crash Report:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description skierpage 2019-04-13 00:36:37 UTC
Application: skrooge (2.19.0BETA)

Qt Version: 5.11.3
Frameworks Version: 5.55.0
Operating System: Linux 5.0.4-200.fc29.x86_64 x86_64
Distribution: "Fedora release 29 (Twenty Nine)"

-- Information about the crash:
- What I was doing when the application crashed:
My bank only provides transactions as a CSV file. The first time I tried to import it failed, and Skrooge trace had a warning "Columns date and amount not found." So I changed the regular expressions in Settings > Configure Skrooge... > Import/Export > CSV > Edit regular expressions... , adding ^check # to Number, ^description to Payee, ^description to comment, and ^withdrawal|^deposit to Amount. Then when I retried import of the CSV, I got this crash.

The last trace output was

##        <virtual SKGError SKGDocument::sendMessage(const QString&, SKGDocument::MessageType, const QString&) RC=[SUC-0]
##        >virtual int SKGImportPluginCsv::getCSVHeaderIndex()
##        <virtual int SKGImportPluginCsv::getCSVHeaderIndex()
##        >virtual QChar SKGImportPluginCsv::getCSVSeparator()
##        <virtual QChar SKGImportPluginCsv::getCSVSeparator()
KCrash: Application 'skrooge' crashing...

I will try to reproduce.

-- Backtrace:
Application: Skrooge (skrooge), signal: Segmentation fault
Using host libthread_db library "/lib64/libthread_db.so.1".
[Current thread is 1 (Thread 0x7fdced28f680 (LWP 28737))]

Thread 9 (Thread 0x7fdc8205c700 (LWP 28767)):
#0  0x00007fdcf0e4572c in pthread_cond_wait@@GLIBC_2.3.2 () at /lib64/libpthread.so.0
#1  0x00007fdcf15296f0 in std::condition_variable::wait(std::unique_lock<std::mutex>&) () at /lib64/libstdc++.so.6
#2  0x00007fdcf388ae92 in WTF::ParkingLot::parkConditionally(void const*, std::function<bool ()>, std::function<void ()>, std::chrono::time_point<std::chrono::_V2::steady_clock, std::chrono::duration<long, std::ratio<1l, 1000000000l> > >) () at /lib64/libQt5WebKit.so.5
#3  0x00007fdcf3889712 in  () at /lib64/libQt5WebKit.so.5
#4  0x00007fdcf38897ee in  () at /lib64/libQt5WebKit.so.5
#5  0x00007fdcf388d68c in  () at /lib64/libQt5WebKit.so.5
#6  0x00007fdcf38b146e in  () at /lib64/libQt5WebKit.so.5
#7  0x00007fdcf0e3f58e in start_thread () at /lib64/libpthread.so.0
#8  0x00007fdcf1204683 in clone () at /lib64/libc.so.6

Thread 8 (Thread 0x7fdc8285d700 (LWP 28766)):
#0  0x00007fdcf0e4572c in pthread_cond_wait@@GLIBC_2.3.2 () at /lib64/libpthread.so.0
#1  0x00007fdcf15296f0 in std::condition_variable::wait(std::unique_lock<std::mutex>&) () at /lib64/libstdc++.so.6
#2  0x00007fdcf388ae92 in WTF::ParkingLot::parkConditionally(void const*, std::function<bool ()>, std::function<void ()>, std::chrono::time_point<std::chrono::_V2::steady_clock, std::chrono::duration<long, std::ratio<1l, 1000000000l> > >) () at /lib64/libQt5WebKit.so.5
#3  0x00007fdcf3889712 in  () at /lib64/libQt5WebKit.so.5
#4  0x00007fdcf38897ee in  () at /lib64/libQt5WebKit.so.5
#5  0x00007fdcf388d68c in  () at /lib64/libQt5WebKit.so.5
#6  0x00007fdcf38b146e in  () at /lib64/libQt5WebKit.so.5
#7  0x00007fdcf0e3f58e in start_thread () at /lib64/libpthread.so.0
#8  0x00007fdcf1204683 in clone () at /lib64/libc.so.6

Thread 7 (Thread 0x7fdc8305e700 (LWP 28765)):
#0  0x00007fdcf0e4572c in pthread_cond_wait@@GLIBC_2.3.2 () at /lib64/libpthread.so.0
#1  0x00007fdcf15296f0 in std::condition_variable::wait(std::unique_lock<std::mutex>&) () at /lib64/libstdc++.so.6
#2  0x00007fdcf388ae92 in WTF::ParkingLot::parkConditionally(void const*, std::function<bool ()>, std::function<void ()>, std::chrono::time_point<std::chrono::_V2::steady_clock, std::chrono::duration<long, std::ratio<1l, 1000000000l> > >) () at /lib64/libQt5WebKit.so.5
#3  0x00007fdcf3889712 in  () at /lib64/libQt5WebKit.so.5
#4  0x00007fdcf38897ee in  () at /lib64/libQt5WebKit.so.5
#5  0x00007fdcf388d68c in  () at /lib64/libQt5WebKit.so.5
#6  0x00007fdcf38b146e in  () at /lib64/libQt5WebKit.so.5
#7  0x00007fdcf0e3f58e in start_thread () at /lib64/libpthread.so.0
#8  0x00007fdcf1204683 in clone () at /lib64/libc.so.6

Thread 6 (Thread 0x7fdcd49ff700 (LWP 28757)):
#0  0x00007fdcef91f2ad in g_mutex_lock () at /lib64/libglib-2.0.so.0
#1  0x00007fdcef8d63f6 in g_main_context_acquire () at /lib64/libglib-2.0.so.0
#2  0x00007fdcef8d7265 in  () at /lib64/libglib-2.0.so.0
#3  0x00007fdcef8d74d0 in g_main_context_iteration () at /lib64/libglib-2.0.so.0
#4  0x00007fdcf18a85ab in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (this=0x7fdc84000b20, flags=...) at kernel/qeventdispatcher_glib.cpp:424
#5  0x00007fdcf1856e0b in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) (this=this@entry=0x7fdcd49fec60, flags=..., flags@entry=...) at ../../include/QtCore/../../src/corelib/global/qflags.h:140
#6  0x00007fdcf16bee86 in QThread::exec() (this=<optimized out>) at ../../include/QtCore/../../src/corelib/global/qflags.h:120
#7  0x00007fdcf16c82fb in QThreadPrivate::start(void*) (arg=0x55a6d88da500) at thread/qthread_unix.cpp:367
#8  0x00007fdcf0e3f58e in start_thread () at /lib64/libpthread.so.0
#9  0x00007fdcf1204683 in clone () at /lib64/libc.so.6

Thread 5 (Thread 0x7fdcd7fff700 (LWP 28755)):
#0  0x00007fdcf0e4572c in pthread_cond_wait@@GLIBC_2.3.2 () at /lib64/libpthread.so.0
#1  0x00007fdcdc6158bb in  () at /usr/lib64/dri/i965_dri.so
#2  0x00007fdcdc6155fb in  () at /usr/lib64/dri/i965_dri.so
#3  0x00007fdcf0e3f58e in start_thread () at /lib64/libpthread.so.0
#4  0x00007fdcf1204683 in clone () at /lib64/libc.so.6

Thread 4 (Thread 0x7fdcde81a700 (LWP 28754)):
#0  0x00007fdcef91f2ad in g_mutex_lock () at /lib64/libglib-2.0.so.0
#1  0x00007fdcef8d68f6 in g_main_context_prepare () at /lib64/libglib-2.0.so.0
#2  0x00007fdcef8d72db in  () at /lib64/libglib-2.0.so.0
#3  0x00007fdcef8d74d0 in g_main_context_iteration () at /lib64/libglib-2.0.so.0
#4  0x00007fdcf18a85ab in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (this=0x7fdcd0000b20, flags=...) at kernel/qeventdispatcher_glib.cpp:424
#5  0x00007fdcf1856e0b in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) (this=this@entry=0x7fdcde819c30, flags=..., flags@entry=...) at ../../include/QtCore/../../src/corelib/global/qflags.h:140
#6  0x00007fdcf16bee86 in QThread::exec() (this=this@entry=0x7fdcf6005060 <(anonymous namespace)::Q_QGS__q_manager::innerFunction()::holder>) at ../../include/QtCore/../../src/corelib/global/qflags.h:120
#7  0x00007fdcf5f89f89 in QDBusConnectionManager::run() (this=0x7fdcf6005060 <(anonymous namespace)::Q_QGS__q_manager::innerFunction()::holder>) at qdbusconnection.cpp:178
#8  0x00007fdcf16c82fb in QThreadPrivate::start(void*) (arg=0x7fdcf6005060 <(anonymous namespace)::Q_QGS__q_manager::innerFunction()::holder>) at thread/qthread_unix.cpp:367
#9  0x00007fdcf0e3f58e in start_thread () at /lib64/libpthread.so.0
#10 0x00007fdcf1204683 in clone () at /lib64/libc.so.6

Thread 3 (Thread 0x7fdcdf5ff700 (LWP 28753)):
#0  0x00007fdcf11f93f1 in poll () at /lib64/libc.so.6
#1  0x00007fdcedb7639f in  () at /lib64/libxcb.so.1
#2  0x00007fdcedb7801a in xcb_wait_for_event () at /lib64/libxcb.so.1
#3  0x00007fdcdf727bf9 in  () at /lib64/libQt5XcbQpa.so.5
#4  0x00007fdcf16c82fb in QThreadPrivate::start(void*) (arg=0x55a6d83c92a0) at thread/qthread_unix.cpp:367
#5  0x00007fdcf0e3f58e in start_thread () at /lib64/libpthread.so.0
#6  0x00007fdcf1204683 in clone () at /lib64/libc.so.6

Thread 2 (Thread 0x7fdced288700 (LWP 28752)):
#0  0x00007fdcf0e4572c in pthread_cond_wait@@GLIBC_2.3.2 () at /lib64/libpthread.so.0
#1  0x00007fdcf15296f0 in std::condition_variable::wait(std::unique_lock<std::mutex>&) () at /lib64/libstdc++.so.6
#2  0x00007fdcf4c8697a in  () at /lib64/libQt5WebKit.so.5
#3  0x00007fdcf4c86aaf in  () at /lib64/libQt5WebKit.so.5
#4  0x00007fdcf152f9a3 in  () at /lib64/libstdc++.so.6
#5  0x00007fdcf0e3f58e in start_thread () at /lib64/libpthread.so.0
#6  0x00007fdcf1204683 in clone () at /lib64/libc.so.6

Thread 1 (Thread 0x7fdced28f680 (LWP 28737)):
[KCrash Handler]
#6  0x00007fdcf1739cb0 in QChar::isSpace() const (this=<synthetic pointer>) at ../../include/QtCore/../../src/corelib/tools/qchar.h:465
#7  0x00007fdcf1739cb0 in QStringAlgorithms<QString const>::isSpace(QChar) (ch=#8  0x00007fdcf1739cb0 in QStringAlgorithms<QString const>::trimmed_helper_positions(QChar const*&, QChar const*&) (end=<synthetic pointer>: <optimized out>, begin=<synthetic pointer>: <optimized out>) at tools/qstringalgorithms_p.h:93
#9  0x00007fdcf1739cb0 in QStringAlgorithms<QString const>::trimmed_helper(QString const&) (str=...) at tools/qstringalgorithms_p.h:104
#10 0x00007fdcf1739cb0 in QString::trimmed_helper(QString const&) (str=...) at tools/qstring.cpp:5531
#11 0x00007fdcd4df3ad4 in QString::trimmed() const & (this=<optimized out>) at /usr/include/qt5/QtCore/qstring.h:436
#12 0x00007fdcd4df3ad4 in SKGImportPluginCsv::importFile() (this=0x55a6d8aaf840) at /usr/src/debug/skrooge-master-0.fc29.x86_64/plugins/import/skrooge_import_csv/skgimportplugincsv.cpp:376
#13 0x00007fdcf70ddb48 in SKGImportExportManager::importFile() (this=this@entry=0x7ffecbf70280) at /usr/include/qt5/QtCore/qtextstream.h:230
#14 0x00007fdcd6a60fb3 in SKGImportExportPlugin::importFiles(QList<QUrl> const&, int, bool) (this=0x55a6d8995a30, iFiles=..., mode=mode@entry=1, iBlockOpenLastModified=iBlockOpenLastModified@entry=false) at /usr/src/debug/skrooge-master-0.fc29.x86_64/plugins/skrooge/skrooge_importexport/skgimportexportplugin.cpp:566
#15 0x00007fdcd6a61f33 in SKGImportExportPlugin::<lambda()>::operator() (__closure=<optimized out>) at /usr/include/qt5/QtCore/qlist.h:151
#16 0x00007fdcd6a61f33 in QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, SKGImportExportPlugin::setupActions(SKGDocument*)::<lambda()> >::call (arg=<optimized out>, f=...) at /usr/include/qt5/QtCore/qobjectdefs_impl.h:128
#17 0x00007fdcd6a61f33 in QtPrivate::Functor<SKGImportExportPlugin::setupActions(SKGDocument*)::<lambda()>, 0>::call<QtPrivate::List<>, void> (arg=<optimized out>, f=...) at /usr/include/qt5/QtCore/qobjectdefs_impl.h:238
#18 0x00007fdcd6a61f33 in QtPrivate::QFunctorSlotObject<SKGImportExportPlugin::setupActions(SKGDocument*)::<lambda()>, 0, QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase *, QObject *, void **, bool *) (which=<optimized out>, this_=<optimized out>, r=<optimized out>, a=<optimized out>, ret=<optimized out>) at /usr/include/qt5/QtCore/qobjectdefs_impl.h:421
#19 0x00007fdcf18801c3 in QtPrivate::QSlotObjectBase::call(QObject*, void**) (a=0x7ffecbf70440, r=0x55a6d8995a30, this=0x55a6d8acb870) at ../../include/QtCore/../../src/corelib/kernel/qobjectdefs_impl.h:376
#20 0x00007fdcf18801c3 in QMetaObject::activate(QObject*, int, int, void**) (sender=0x55a6d8ad14d0, signalOffset=<optimized out>, local_signal_index=<optimized out>, argv=<optimized out>) at kernel/qobject.cpp:3754
#21 0x00007fdcf5923a36 in QAction::triggered(bool) () at /lib64/libQt5Widgets.so.5
#22 0x00007fdcf5926100 in QAction::activate(QAction::ActionEvent) () at /lib64/libQt5Widgets.so.5
#23 0x00007fdcf5a9b11c in  () at /lib64/libQt5Widgets.so.5
#24 0x00007fdcf5aa27c4 in  () at /lib64/libQt5Widgets.so.5
#25 0x00007fdcf5aa380b in QMenu::mouseReleaseEvent(QMouseEvent*) () at /lib64/libQt5Widgets.so.5
#26 0x00007fdcf5969378 in QWidget::event(QEvent*) () at /lib64/libQt5Widgets.so.5
#27 0x00007fdcf5aa5ebb in QMenu::event(QEvent*) () at /lib64/libQt5Widgets.so.5
#28 0x00007fdcf592a285 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /lib64/libQt5Widgets.so.5
#29 0x00007fdcf5931be8 in QApplication::notify(QObject*, QEvent*) () at /lib64/libQt5Widgets.so.5
#30 0x00007fdcf1857ec6 in QCoreApplication::notifyInternal2(QObject*, QEvent*) (receiver=0x55a6d8bed790, event=0x7ffecbf70a40) at kernel/qcoreapplication.cpp:1047
#31 0x00007fdcf5930edd in QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool) () at /lib64/libQt5Widgets.so.5
#32 0x00007fdcf59844d3 in  () at /lib64/libQt5Widgets.so.5
#33 0x00007fdcf5986cbe in  () at /lib64/libQt5Widgets.so.5
#34 0x00007fdcf592a285 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /lib64/libQt5Widgets.so.5
#35 0x00007fdcf59319a0 in QApplication::notify(QObject*, QEvent*) () at /lib64/libQt5Widgets.so.5
#36 0x00007fdcf1857ec6 in QCoreApplication::notifyInternal2(QObject*, QEvent*) (receiver=0x7fdcd800f8e0, event=0x7ffecbf70e20) at kernel/qcoreapplication.cpp:1047
#37 0x00007fdcf21b34d3 in QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent*) () at /lib64/libQt5Gui.so.5
#38 0x00007fdcf21b55d5 in QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent*) () at /lib64/libQt5Gui.so.5
#39 0x00007fdcf219070b in QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) () at /lib64/libQt5Gui.so.5
#40 0x00007fdcdf7bb85f in  () at /lib64/libQt5XcbQpa.so.5
#41 0x00007fdcf1856e0b in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) (this=this@entry=0x7ffecbf710a0, flags=..., flags@entry=...) at ../../include/QtCore/../../src/corelib/global/qflags.h:140
#42 0x00007fdcf185eed6 in QCoreApplication::exec() () at ../../include/QtCore/../../src/corelib/global/qflags.h:120
#43 0x000055a6d80b4ebe in main(int, char**) (argc=<optimized out>, argv=<optimized out>) at /usr/src/debug/skrooge-master-0.fc29.x86_64/skrooge/main.cpp:212
[Inferior 1 (process 28737) detached]

Reported using DrKonqi
Comment 1 skierpage 2019-04-13 07:10:04 UTC
I narrowed the problem is. My bank inserts extra lines of text in the CSV file *after* the row of column header labels, e.g.:

"Date","Type","Number","Payee","Withdrawal (-)","Amount"
"Pending Transactions are not reflected within this sort criterion."
"Posted Transactions"
"12/31/2018","INTADJUST","","Interest Paid","","$2.51"
...

The first bogus extra line (2) triggers the segfault in QChar::isSpace() in comment 0. The second bogus extra line (3) causes a different segfault in QArrayData::data(), but the rest of the backtrace is about the same.

The workaround is to delete anything after the line of column headers that doesn't exactly match the layout they specify.

It would be nice if Skrooge didn't crash and displayed a brown warning message such as "Invalid lines 2,3 in CSV file ignored." (There are already other errors in import that appear in trace output but are not shown to the user, such as "Date format not supported" and "Columns date and amount not found. Set import parameters in settings (Configure Skrooge... / Import/Export / CSV / Edit regular expressions...)"

Another fix would be to document this limitation in the Skrooge handbook under CSV import:
"The CSV file must contain a line of column header labels and Skrooge must be able to find Date and Amount columns in it (you can see and modify the label matching in Settings > Configure Skrooge... > Import/Export > CSV > Edit regular expressions...). All the lines in the CSV file after this line of column header labels must match its format."
Comment 2 Stephane MANKOWSKI 2019-04-13 21:12:55 UTC
Git commit e3d977287c660e826ae8470e698a35515a9fcc39 by Stephane MANKOWSKI.
Committed on 13/04/2019 at 21:12.
Pushed by smankowski into branch 'master'.

crash importing a CSV

M  +1    -0    CHANGELOG
M  +15   -10   plugins/import/skrooge_import_csv/skgimportplugincsv.cpp
A  +4    -0    tests/input/skgtestimportcsv/406488.csv
M  +22   -0    tests/skgbankmodelertest/skgtestimportcsv.cpp

https://commits.kde.org/skrooge/e3d977287c660e826ae8470e698a35515a9fcc39