rtklibexplorer / RTKLIB

A version of RTKLIB optimized for low cost GNSS receivers, especially u-blox receivers. It is based on RTKLIB 2.4.3 and is kept reasonably closely synced to that branch. This software is provided “AS IS” without any warranties of any kind so please be careful, especially if using it in any kind of real-time application.
http://rtkexplorer.com/
Other
641 stars 250 forks source link

qt_qui branch: rtknavi_qt crashes after pressing "Start" button #281

Closed dwrobel closed 4 months ago

dwrobel commented 4 months ago

rtknavi_qt compiled on Fedora 39, from latest sources bf9284d1daae00528f4dfbb890efc43d85bbfa17 _(qt_qui branch), crashes as following when pressing Start button (it's irrelevant if you've configured any "Input Stream" or not)_:

** buffer overflow detected ***: terminated

Thread 1 "rtknavi_qt" received signal SIGABRT, Aborted.
__pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44
44        return INTERNAL_SYSCALL_ERROR_P (ret) ? INTERNAL_SYSCALL_ERRNO (ret) : 0;
(gdb) bt
#0  __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44
#1  0x00007f8ea04ae8a3 in __pthread_kill_internal (signo=6, threadid=<optimized out>) at pthread_kill.c:78
#2  0x00007f8ea045c8ee in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#3  0x00007f8ea04448ff in __GI_abort () at abort.c:79
#4  0x00007f8ea04457d0 in __libc_message (fmt=fmt@entry=0x7f8ea05c2309 "*** %s ***: terminated\n") at ../sysdeps/posix/libc_fatal.c:150
#5  0x00007f8ea0542079 in __GI___fortify_fail (msg=msg@entry=0x7f8ea05c22f0 "buffer overflow detected") at fortify_fail.c:24
#6  0x00007f8ea0541a34 in __GI___chk_fail () at chk_fail.c:28
#7  0x00007f8ea0543435 in __strcpy_chk
    (dest=0x7f8ea26bf8c0 <localdir.lto_priv> "", src=0x5570d6fcb6e8 '\377' <repeats 44 times>, "\370\366\366\377\232hh\377\225``\377\376\375\375", '\377' <repeats 17 times>, "\232hh\377\276\234\234\377\343\324\324\377ɭ\255\377з\267\377\365\360\360\377\376\376\376\377\377\377\377\377\376\376\376\377\377\377\377\377\376\377\377\377\246}~\377\253f^\377\277gU\377\255f\\\377\264\220\220\377\372\370\370\377\376\376\376\377\376\376\376", '\377' <repeats 13 times>, "\257\210\210\377\250~~\377\376\375\375\377\377\377\377\377\376\376\376\377\377\377\377\377\342\324\324\377\230ee\377\270\224\224\377"..., destlen=1024) at strcpy_chk.c:30
#8  0x00005570d4e838bb in MainWindow::serverStart (this=<optimized out>) at /usr/src/debug/rtklib-2.4.3.b34i-14.20240515gitbf9284d.fc39.x86_64/app/qtapp/rtknavi_qt/navimain.cpp:1140
#9  0x00007f8ea0c01951 in QtPrivate::QSlotObjectBase::call (a=0x7ffc478b81c0, r=0x7ffc478b8f80, this=0x5570d76fb760) at /usr/src/debug/qt6-qtbase-6.6.2-1.fc39.x86_64/src/corelib/kernel/qobjectdefs_impl.h:433
#10 doActivate<false> (sender=0x5570d6750670, signal_index=9, argv=0x7ffc478b81c0) at /usr/src/debug/qt6-qtbase-6.6.2-1.fc39.x86_64/src/corelib/kernel/qobject.cpp:4039
#11 0x00007f8ea0bf7f67 in QMetaObject::activate (sender=sender@entry=0x5570d6750670, m=m@entry=0x7f8ea2372dc0, local_signal_index=local_signal_index@entry=2, argv=argv@entry=0x7ffc478b81c0)
    at /usr/src/debug/qt6-qtbase-6.6.2-1.fc39.x86_64/src/corelib/kernel/qobject.cpp:4099
#12 0x00007f8ea1ef2674 in QAbstractButton::clicked (this=this@entry=0x5570d6750670, _t1=<optimized out>) at /usr/src/debug/qt6-qtbase-6.6.2-1.fc39.x86_64/redhat-linux-build/src/widgets/Widgets_autogen/include/moc_qabstractbutton.cpp:408
#13 0x00007f8ea1ef28ff in QAbstractButtonPrivate::emitClicked (this=0x5570d6758e80) at /usr/src/debug/qt6-qtbase-6.6.2-1.fc39.x86_64/src/widgets/widgets/qabstractbutton.cpp:379
#14 0x00007f8ea1ef4000 in QAbstractButtonPrivate::click (this=0x5570d6758e80) at /usr/src/debug/qt6-qtbase-6.6.2-1.fc39.x86_64/src/widgets/widgets/qabstractbutton.cpp:372
#15 0x00007f8ea1ef4208 in QAbstractButton::mouseReleaseEvent (this=0x5570d6750670, e=0x7ffc478b8810) at /usr/src/debug/qt6-qtbase-6.6.2-1.fc39.x86_64/src/widgets/widgets/qabstractbutton.cpp:974
#16 0x00007f8ea1e1e648 in QWidget::event (this=0x5570d6750670, event=0x7ffc478b8810) at /usr/src/debug/qt6-qtbase-6.6.2-1.fc39.x86_64/src/widgets/kernel/qwidget.cpp:9339
#17 0x00007f8ea1dc3228 in QApplicationPrivate::notify_helper (this=this@entry=0x5570d63d7340, receiver=receiver@entry=0x5570d6750670, e=e@entry=0x7ffc478b8810)
    at /usr/src/debug/qt6-qtbase-6.6.2-1.fc39.x86_64/src/widgets/kernel/qapplication.cpp:3296
#18 0x00007f8ea1dccdba in QApplication::notify (this=<optimized out>, receiver=0x5570d6750670, e=<optimized out>) at /usr/src/debug/qt6-qtbase-6.6.2-1.fc39.x86_64/src/widgets/kernel/qapplication.cpp:2782
#19 0x00007f8ea0ba0948 in QCoreApplication::notifyInternal2 (receiver=0x5570d6750670, event=0x7ffc478b8810) at /usr/src/debug/qt6-qtbase-6.6.2-1.fc39.x86_64/src/corelib/kernel/qcoreapplication.cpp:1121
#20 0x00007f8ea0ba0b5d in QCoreApplication::sendSpontaneousEvent (receiver=<optimized out>, event=<optimized out>) at /usr/src/debug/qt6-qtbase-6.6.2-1.fc39.x86_64/src/corelib/kernel/qcoreapplication.cpp:1553
#21 0x00007f8ea1dcb5b3 in QApplicationPrivate::sendMouseEvent (receiver=receiver@entry=0x5570d6750670, event=event@entry=0x7ffc478b8810, alienWidget=<optimized out>, 
    alienWidget@entry=0x5570d6750670, nativeWidget=0x7ffc478b8f80, buttonDown=buttonDown@entry=0x7f8ea23b6860 <qt_button_down>, lastMouseReceiver=..., spontaneous=true, onlyDispatchEnterLeave=false)
    at /usr/src/debug/qt6-qtbase-6.6.2-1.fc39.x86_64/src/widgets/kernel/qapplication.cpp:2366
#22 0x00007f8ea1e32177 in QWidgetWindow::handleMouseEvent (this=0x5570d76ff7d0, event=0x7ffc478b8ad0) at /usr/src/debug/qt6-qtbase-6.6.2-1.fc39.x86_64/src/widgets/kernel/qwidgetwindow.cpp:653
#23 0x00007f8ea1e35040 in QWidgetWindow::event (this=0x5570d76ff7d0, event=0x7ffc478b8ad0) at /usr/src/debug/qt6-qtbase-6.6.2-1.fc39.x86_64/src/widgets/kernel/qwidgetwindow.cpp:267
#24 0x00007f8ea1dc3228 in QApplicationPrivate::notify_helper (this=<optimized out>, receiver=0x5570d76ff7d0, e=0x7ffc478b8ad0) at /usr/src/debug/qt6-qtbase-6.6.2-1.fc39.x86_64/src/widgets/kernel/qapplication.cpp:3296
#25 0x00007f8ea0ba0948 in QCoreApplication::notifyInternal2 (receiver=0x5570d76ff7d0, event=0x7ffc478b8ad0) at /usr/src/debug/qt6-qtbase-6.6.2-1.fc39.x86_64/src/corelib/kernel/qcoreapplication.cpp:1121
#26 0x00007f8ea0ba0b5d in QCoreApplication::sendSpontaneousEvent (receiver=<optimized out>, event=<optimized out>) at /usr/src/debug/qt6-qtbase-6.6.2-1.fc39.x86_64/src/corelib/kernel/qcoreapplication.cpp:1553
#27 0x00007f8ea140b57f in QGuiApplicationPrivate::processMouseEvent (e=0x7f8e6403ec10) at /usr/src/debug/qt6-qtbase-6.6.2-1.fc39.x86_64/src/gui/kernel/qguiapplication.cpp:2325
#28 0x00007f8ea146a29c in QWindowSystemInterface::sendWindowSystemEvents (flags=...) at /usr/src/debug/qt6-qtbase-6.6.2-1.fc39.x86_64/src/gui/kernel/qwindowsysteminterface.cpp:1109
#29 0x00007f8ea1944c74 in userEventSourceDispatch (source=<optimized out>) at /usr/src/debug/qt6-qtbase-6.6.2-1.fc39.x86_64/src/gui/platform/unix/qeventdispatcher_glib.cpp:38
#30 0x00007f8ea0911e5c in g_main_context_dispatch_unlocked.lto_priv () at /lib64/libglib-2.0.so.0
#31 0x00007f8ea096cf18 in g_main_context_iterate_unlocked.isra () at /lib64/libglib-2.0.so.0
#32 0x00007f8ea090fad3 in g_main_context_iteration () at /lib64/libglib-2.0.so.0
#33 0x00007f8ea0e6c11f in QEventDispatcherGlib::processEvents (this=0x5570d63d95b0, flags=...) at /usr/src/debug/qt6-qtbase-6.6.2-1.fc39.x86_64/src/corelib/kernel/qeventdispatcher_glib.cpp:393
#34 0x00007f8ea0bad70b in QEventLoop::exec (this=this@entry=0x7ffc478b8f00, flags=..., flags@entry=...) at /usr/src/debug/qt6-qtbase-6.6.2-1.fc39.x86_64/src/corelib/global/qflags.h:34
#35 0x00007f8ea0ba950d in QCoreApplication::exec () at /usr/src/debug/qt6-qtbase-6.6.2-1.fc39.x86_64/src/corelib/global/qflags.h:74
#36 0x00007f8ea13fafbd in QGuiApplication::exec () at /usr/src/debug/qt6-qtbase-6.6.2-1.fc39.x86_64/src/gui/kernel/qguiapplication.cpp:1925
#37 0x00007f8ea1dc3199 in QApplication::exec () at /usr/src/debug/qt6-qtbase-6.6.2-1.fc39.x86_64/src/widgets/kernel/qapplication.cpp:2574
#38 0x00005570d4df48ec in main (argc=<optimized out>, argv=<optimized out>) at /usr/src/debug/rtklib-2.4.3.b34i-14.20240515gitbf9284d.fc39.x86_64/app/qtapp/rtknavi_qt/main.cpp:11
(gdb) fr 8
#8  0x00005570d4e838bb in MainWindow::serverStart (this=<optimized out>) at /usr/src/debug/rtklib-2.4.3.b34i-14.20240515gitbf9284d.fc39.x86_64/app/qtapp/rtknavi_qt/navimain.cpp:1140
1140        strsetdir(optDialog->fileOptions.tempdir);
(gdb) 

It looks that optDialog->fileOptions.tempdir (see frame 8) contains a garbage.

ourairquality commented 4 months ago

Could you add a printf of the argument past to strsetdir to see if it is garbage or if it is a very long string that overflows the static buffer.

Fwiw I have been working to harden the code, but have not got to the qt app yet. The console apps are now passing many tests. It my experimental code strsetdir() guards the destination buffer, see https://github.com/ourairquality/RTKLIB/blob/oaq-rewrite/src/stream.c#L3078 and might have reported a clearer error. But that can not protect against having been passed garbage. This experimental code is not adapted to the qt_gui branch, but the demo5 qt code runs, and an attempt has been made to apply respective changes to the windows code. There is a slight update to the qu_gui branch pending https://github.com/rtklibexplorer/RTKLIB/pull/271 There in one outstanding patch to the demo5 qt app code, see https://github.com/rtklibexplorer/RTKLIB/pull/273, but this was applied to the qt_gui branch.

dwrobel commented 4 months ago

Could you add a printf of the argument past to strsetdir to see if it is garbage or if it is a very long string that overflows the static buffer.

Actually, gdb partially dumps its value, see arguments passed to __strcpy_chk() in frame 7:

(dest=0x7f8ea26bf8c0 <localdir.lto_priv> "", src=0x5570d6fcb6e8 '\377' <repeats 44 times>, "\370\366\366\377\232hh\377\225``\377\376\375\375", '\377' <repeats 17 times>, "\232hh\377\276\234\234\377\343\324\324\377ɭ\255\377з\267\377\365\360\360\377\376\376\376\377\377\377\377\377\376\376\376\377\377\377\377\377\376\377\377\377\246}~\377\253f^\377\277gU\377\255f\\\377\264\220\220\377\372\370\370\377\376\376\376\377\376\376\376", '\377' <repeats 13 times>, "\257\210\210\377\250~~\377\376\375\375\377\377\377\377\377\376\376\376\377\377\377\377\377\342\324\324\377\230ee\377\270\224\224\377"..., destlen=1024) at strcpy_chk.c:30

FYI, the strlen(optDialog->fileOptions.tempdir) returns 3576.

ourairquality commented 4 months ago

Might be initialized from the constructor in appcmn_qt/navi_post_opt.cpp, can you check that the following is working:

    if (options == NaviOptions)
        strncpy(filopt.tempdir, qPrintable(ui->lELocalDirectory->text()), MAXSTRPATH-1);

Btw these uses of strncpy are also unsafe as they do not ensure that the string is nul terminated.

Also truncating a path may also not be great. Might consider adding a string-copy-or-default function to more gracefully fail.

ourairquality commented 4 months ago

Sorry, that was the load/save options code paths. As a work-around open the options and then close, before starting.

dwrobel commented 4 months ago

Might be initialized from the constructor in appcmn_qt/navi_post_opt.cpp, can you check that the following is working:

No, it doesn't. The following method:

(gdb) b OptDialog::save
Breakpoint 2 at 0x56046b4fc070: file ../appcmn_qt/navi_post_opt.cpp, line 935.

is not invoked at all in those two scenarios I'm using: 1) Launch the program, press Start button (as a first operation). 2) Lauch the program, press I button (Define input streams), then activate "(1) Rover" with Stream Type: "TCP Client", Stream Options: { Server Address: localhost, Port: 12345}, then press Start button.

Once I go to "Options" and then use "Save..." then the OptDialog::save method is invoked:

(gdb) b 1094
Breakpoint 3 at 0x56466e7011a6: file ../appcmn_qt/navi_post_opt.cpp, line 1094.
(gdb) c
Continuing.
[Thread 0x7f6150e006c0 (LWP 2059826) exited]
[Thread 0x7f61522006c0 (LWP 2059825) exited]
[Thread 0x7f61320006c0 (LWP 2059824) exited]
[Thread 0x7f61518006c0 (LWP 2059823) exited]

Thread 1 "rtknavi_qt" hit Breakpoint 3, OptDialog::save (this=0x564670355b70, 
    file=...) at ../appcmn_qt/navi_post_opt.cpp:1094
1094        if (options == NaviOptions)
(gdb) p options
$1 = 0
(gdb) n
1095            strncpy(filopt.tempdir, qPrintable(ui->lELocalDirectory->text()), MAXSTRPATH-1);
(gdb) n
1100        time2str(utc2gpst(timeget()), s, 0);
(gdb) p filopt.tempdir
$2 = "C:\\Temp", '\000' <repeats 1016 times>
(gdb) c
Continuing.

and the "Start" button is working fine.

JensReimann commented 4 months ago

Please give the lastest version in the qt_gui branch a try. There was a missing initialization in the options dialog.

And: please keep reporting bugs. It is nearly impossible to test every functionality of such a big piece software alone.

dwrobel commented 4 months ago

Please give the lastest version in the qt_gui branch a try. There was a missing initialization in the options dialog.

Tested using 68a355b and it works fine. Thanks for the fix.