Skip to content
This repository has been archived by the owner on Feb 12, 2023. It is now read-only.

Segmentation fault when opening a contact #6412

Open
meyou69 opened this issue Nov 13, 2021 · 5 comments · May be fixed by #6621
Open

Segmentation fault when opening a contact #6412

meyou69 opened this issue Nov 13, 2021 · 5 comments · May be fixed by #6621

Comments

@meyou69
Copy link

meyou69 commented Nov 13, 2021

Brief Description

OS: Fedora 35
qTox version: qTox v1.17.3-316-g12fc33ee
Commit hash: c0e9a3b
toxcore: toxcore version 0.2.12
Qt: version: 5.15.2

Reproducible: Always

Steps to reproduce
  1. Have at least one tox contact in your friends list
  2. Click on that contact to open your conversation history with them. The contact doesn't have to be online
  3. Close the conversation window with them
  4. Click on that same contact again to open your conversation history with them a second time
  5. If the conversation history window opens without any issues, go back to step 3 and repeat all the steps from there again
  6. Eventually, when clicking on the contact to open their conversation history window, the entire process will crash. If qTox was open from bash in a terminal window in the background, bash will report a segmentation fault when the process crashes
Observed Behavior

Process crashes unexpectedly.

Expected Behavior

Regardless of how many times I close and re-open the exact same conversation history window with my contact, the qTox process should never crash.

Additional Info

Fedora doesn't have a package with the debug symbols for qTox. As such, I cannot provide a reliable backtrace with GDB, sadly.
For what it's worth, as unreliable as it is, the backtrace that I did get can be found at: https://pastebin.com/a5xL4az1

I don't have much technical expertise but this looks like a nullptr de-referencing issue to me.

The qtox.log can be found at https://pastebin.com/3FGYDCxJ
Please note that both the backtrace and the log are set to be auto-deleted after 1 calendar Year since the moment they were created (around the same time that this issue was created).

@anthonybilinski
Copy link
Member

From the backlog:

#0  0x0000000000000000 in ?? ()
#1  0x000055555573a180 in Widget::openDialog(GenericChatroomWidget*, bool) ()
#2  0x00007ffff518d3a9 in QtPrivate::QSlotObjectBase::call (a=0x7fffffffce30, r=<optimized out>, this=0x5555571cfb70)
    at ../../include/QtCore/../../src/corelib/kernel/qobjectdefs_impl.h:398
#3  doActivate<false> (sender=0x555555ea81d0, signal_index=7, argv=0x7fffffffce30) at kernel/qobject.cpp:3886

It's a bit hard to say what pointer in Widget::openDialog is null, a lot are accessed and nothing seems obviously wrong from inspection.

I'm unable to reproduce this at either v1.17.3-316-g12fc33ee or current master tip (65c42eb), my steps are:

  1. Have 1 group and 4 friends in my list, all friends offline.
  2. Enable Settings->UI->"Multiple windows mode" and "Open each chat in an individual window"
  3. Open and close the chat by clicking the friend list item for a friend then the x on the chat, about 100 times at each version in quick succession.

Does this seems consistent with your repo?
Was your repro rate quite low, i.e. might not be seen for hundreds of attempts?
Is it possible other things contributed, i.e. friend list changing, the friend you're opening coming online, something like that?

@meyou69
Copy link
Author

meyou69 commented Feb 10, 2022

Was your repro rate quite low, i.e. might not be seen for hundreds of attempts?
Is it possible other things contributed, i.e. friend list changing, the friend you're opening coming online, something like that?

I don't think any of those are the issue. My friends list was mostly static and this usually happened while my friend was offline.

I'm unable to reproduce this at either v1.17.3-316-g12fc33ee or current master tip (65c42eb), my steps are:

If I follow your exact steps, the issue doesn't reproduce on my end either.
But if you do not enable the "Open each chat in an individual window" option in the settings window but keep the "Multiple windows mode" enabled, then the crash always reproduces on my end. Maybe the technical solution would be to always have "Open each chat in an individual window" enabled but, if that's the case, that option shouldn't be disabled by default, as it is on my end. How was I supposed to know that it needed to always be enabled? If one checkbox is not supposed to be disabled while the other is already enabled then why have two checkboxes in the first place?

Open and close the chat by clicking the friend list item for a friend then the x on the chat, about 100 times at each version in quick succession.

No, this shouldn't take 100 times. It happens on my end when I click on the same contact just two times. 100 times is overkill. And if I already opened the contact with "Open each chat in an individual window" enabled and then I disable that option, clicking on that contact again will make the process crash again

@anthonybilinski
Copy link
Member

I wasn't trying to imply that the settings are required to be used together, the crash is a bug and the dependency of the settings is reflected accurately in the menu already.

Interesting on my host system (Arch) with I still couldn't reproduce the issue even with "Open each chat in an individual window", with ~100 attempts. Checking on Fedora 35 though, it happened first try on the latest commit.

They're both using Qt 5.15.2, so it doesn't seem to just be a Qt bug that was fixed between versions. I'll keep investigating now that I have a repro.

@meyou69
Copy link
Author

meyou69 commented Feb 11, 2022

Thank you

@anthonybilinski
Copy link
Member

full backtrace here:

#0  QWidget::show (this=0x60e0001b71a0) at kernel/qwidget.cpp:7662
#1  0x000000000094e71a in Widget::openDialog (this=0x6160000ca580, widget=0x6110002ca8c0, newWindow=false) at /home/abilinski/builds/qTox/src/widget/widget.cpp:1397
#2  0x000000000094e1cb in Widget::onChatroomWidgetClicked (this=0x6160000ca580, widget=0x6110002ca8c0) at /home/abilinski/builds/qTox/src/widget/widget.cpp:1354
#3  0x00000000009aff2a in QtPrivate::FunctorCall<QtPrivate::IndexesList<0>, QtPrivate::List<GenericChatroomWidget*>, void, void (Widget::*)(GenericChatroomWidget*)>::call (f=(void (Widget::*)(Widget * const, GenericChatroomWidget *)) 0x94e194 <Widget::onChatroomWidgetClicked(GenericChatroomWidget*)>, o=0x6160000ca580, arg=0x7fffffffbef0) at /usr/include/qt5/QtCore/qobjectdefs_impl.h:152
#4  0x00000000009a475a in QtPrivate::FunctionPointer<void (Widget::*)(GenericChatroomWidget*)>::call<QtPrivate::List<GenericChatroomWidget*>, void> (f=(void (Widget::*)(Widget * const, GenericChatroomWidget *)) 0x94e194 <Widget::onChatroomWidgetClicked(GenericChatroomWidget*)>, o=0x6160000ca580, arg=0x7fffffffbef0) at /usr/include/qt5/QtCore/qobjectdefs_impl.h:185
#5  0x000000000099ab45 in QtPrivate::QSlotObject<void (Widget::*)(GenericChatroomWidget*), QtPrivate::List<GenericChatroomWidget*>, void>::impl (which=1, this_=0x603000a2a1b0, r=0x6160000ca580, a=0x7fffffffbef0, ret=0x0) at /usr/include/qt5/QtCore/qobjectdefs_impl.h:418
#6  0x00007ffff43603e9 in QtPrivate::QSlotObjectBase::call (a=0x7fffffffbef0, r=<optimized out>, this=0x603000a2a1b0) at ../../include/QtCore/../../src/corelib/kernel/qobjectdefs_impl.h:398
#7  doActivate<false> (sender=0x6110002ca8c0, signal_index=7, argv=0x7fffffffbef0) at kernel/qobject.cpp:3886
#8  0x00000000004adcd9 in GenericChatroomWidget::chatroomWidgetClicked (this=0x6110002ca8c0, _t1=0x6110002ca8c0) at /home/abilinski/builds/qTox/_build/qtox_static_autogen/WFD7YQQOTJ/moc_genericchatroomwidget.cpp:270
#9  0x00000000008d5fb6 in GenericChatroomWidget::mouseReleaseEvent (this=0x6110002ca8c0, event=0x7fffffffc190) at /home/abilinski/builds/qTox/src/widget/genericchatroomwidget.cpp:172
#10 0x00007ffff4e45e7e in QWidget::event (this=this@entry=0x6110002ca8c0, event=event@entry=0x7fffffffc190) at kernel/qwidget.cpp:9020
#11 0x00007ffff4ef3942 in QFrame::event (this=0x6110002ca8c0, e=0x7fffffffc190) at widgets/qframe.cpp:550
#12 0x00007ffff4e03443 in QApplicationPrivate::notify_helper (this=this@entry=0x613000000040, receiver=receiver@entry=0x6110002ca8c0, e=e@entry=0x7fffffffc190) at kernel/qapplication.cpp:3632
#13 0x00007ffff4e0b074 in QApplication::notify (this=0x7fffffffc190, receiver=0x6070002ae5d0, e=0x7fffffffc450) at kernel/qapplication.cpp:3076
#14 0x00007ffff432c7d8 in QCoreApplication::notifyInternal2 (receiver=0x6070002ae5d0, event=0x7fffffffc450) at kernel/qcoreapplication.cpp:1064
#15 0x00007ffff4e09b57 in QApplicationPrivate::sendMouseEvent (receiver=receiver@entry=0x6070002ae5d0, event=event@entry=0x7fffffffc450, alienWidget=alienWidget@entry=0x6070002ae5d0, nativeWidget=0x6160000ca580, buttonDown=<optimized out>, lastMouseReceiver=..., spontaneous=true, onlyDispatchEnterLeave=false) at kernel/qapplication.cpp:2614
#16 0x00007ffff4e5f450 in QWidgetWindow::handleMouseEvent (this=0x6080002665a0, event=0x7fffffffc700) at kernel/qwidgetwindow.cpp:683
#17 0x00007ffff4e626e5 in QWidgetWindow::event (this=0x6080002665a0, event=0x7fffffffc700) at kernel/qwidgetwindow.cpp:300
#18 0x00007ffff4e03443 in QApplicationPrivate::notify_helper (this=<optimized out>, receiver=0x6080002665a0, e=0x7fffffffc700) at kernel/qapplication.cpp:3632
#19 0x00007ffff432c7d8 in QCoreApplication::notifyInternal2 (receiver=0x6080002665a0, event=0x7fffffffc700) at kernel/qcoreapplication.cpp:1064
#20 0x00007ffff477fb98 in QGuiApplicationPrivate::processMouseEvent (e=0x60b000519260) at kernel/qguiapplication.cpp:2275
#21 0x00007ffff475fc9c in QWindowSystemInterface::sendWindowSystemEvents (flags=...) at kernel/qwindowsysteminterface.cpp:1169
#22 0x00007fffd8a35ca4 in userEventSourceDispatch(_GSource*, int (*)(void*), void*) () from /lib64/libQt5WaylandClient.so.5
#23 0x00007ffff2ae233f in g_main_dispatch (context=0x60f000007930) at ../glib/gmain.c:3381
#24 g_main_context_dispatch (context=0x60f000007930) at ../glib/gmain.c:4099
#25 0x00007ffff2b37288 in g_main_context_iterate.constprop.0 (context=context@entry=0x60f000007930, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../glib/gmain.c:4175
#26 0x00007ffff2adf9e3 in g_main_context_iteration (context=0x60f000007930, may_block=1) at ../glib/gmain.c:4240
#27 0x00007ffff437dbb8 in QEventDispatcherGlib::processEvents (this=0x603000014ad0, flags=...) at kernel/qeventdispatcher_glib.cpp:423
#28 0x00007ffff432b1e2 in QEventLoop::exec (this=this@entry=0x7fffffffca90, flags=..., flags@entry=...) at ../../include/QtCore/../../src/corelib/global/qflags.h:69
#29 0x00007ffff4333724 in QCoreApplication::exec () at ../../include/QtCore/../../src/corelib/global/qflags.h:121
#30 0x0000000000455097 in main (argc=1, argv=0x7fffffffe068) at /home/abilinski/builds/qTox/src/main.cpp:433

so nothing like us just referencing a null pointer. It's crashing inside of(?) QWidget::show, but the bt just points to the first line of the definition. The entire function is this:

void QWidget::show()
{
    Qt::WindowState defaultState = QGuiApplicationPrivate::platformIntegration()->defaultWindowState(data->window_flags);
    if (defaultState == Qt::WindowFullScreen)
        showFullScreen();
    else if (defaultState == Qt::WindowMaximized)
        showMaximized();
    else
        setVisible(true); // Don't call showNormal() as not to clobber Qt::Window(Max/Min)imized
}

defaultState is optimized out in my case, this is valid, I was poking around and could call isActiveWindow(), then called isVisible() and the AddressSanitizer caught a user-after-free:

(gdb) p isVisible()
=================================================================
==11469==ERROR: AddressSanitizer: heap-use-after-free on address 0x60e0001b71c8 at pc 0x000000528cf5 bp 0x7fffffffba00 sp 0x7fffffffb9f8
READ of size 8 at 0x60e0001b71c8 thread T0
    #0 0x528cf4 in QWidget::testAttribute(Qt::WidgetAttribute) const /usr/include/qt5/QtWidgets/qwidget.h:883
    #1 0x528b13 in QWidget::isVisible() const /usr/include/qt5/QtWidgets/qwidget.h:845
    #2 0x7fffffffba7e  ([stack]+0x1da7e)

0x60e0001b71c8 is located 40 bytes inside of 152-byte region [0x60e0001b71a0,0x60e0001b7238)
freed by thread T0 here:
    #0 0x7ffff7692a87 in operator delete(void*) (/lib64/libasan.so.6+0xb0a87)
    #1 0x771e28 in ContentDialog::~ContentDialog() /home/abilinski/builds/qTox/src/widget/contentdialog.cpp:146
    #2 0x7ffff4356d70 in QObject::event(QEvent*) (/lib64/libQt5Core.so.5+0x2d0d70)
    #3 0x90d68d in ActivateDialog::event(QEvent*) /home/abilinski/builds/qTox/src/widget/tool/activatedialog.cpp:36
    #4 0x775242 in ContentDialog::event(QEvent*) /home/abilinski/builds/qTox/src/widget/contentdialog.cpp:469
    #5 0x7ffff4e03442 in QApplicationPrivate::notify_helper(QObject*, QEvent*) (/lib64/libQt5Widgets.so.5+0x1ae442)

previously allocated by thread T0 here:
    #0 0x7ffff7692087 in operator new(unsigned long) (/lib64/libasan.so.6+0xb0087)
    #1 0x953801 in Widget::createContentDialog() const /home/abilinski/builds/qTox/src/widget/widget.cpp:1844
    #2 0x94e703 in Widget::openDialog(GenericChatroomWidget*, bool) /home/abilinski/builds/qTox/src/widget/widget.cpp:1394
    #3 0x94e1ca in Widget::onChatroomWidgetClicked(GenericChatroomWidget*) /home/abilinski/builds/qTox/src/widget/widget.cpp:1354
    #4 0x9aff29 in QtPrivate::FunctorCall<QtPrivate::IndexesList<0>, QtPrivate::List<GenericChatroomWidget*>, void, void (Widget::*)(GenericChatroomWidget*)>::call(void (Widget::*)(GenericChatroomWidget*), Widget*, void**) /usr/include/qt5/QtCore/qobjectdefs_impl.h:152
    #5 0x9a4759 in void QtPrivate::FunctionPointer<void (Widget::*)(GenericChatroomWidget*)>::call<QtPrivate::List<GenericChatroomWidget*>, void>(void (Widget::*)(GenericChatroomWidget*), Widget*, void**) /usr/include/qt5/QtCore/qobjectdefs_impl.h:185
    #6 0x99ab44 in QtPrivate::QSlotObject<void (Widget::*)(GenericChatroomWidget*), QtPrivate::List<GenericChatroomWidget*>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) /usr/include/qt5/QtCore/qobjectdefs_impl.h:418
    #7 0x7ffff43603e8 in void doActivate<false>(QObject*, int, void**) (/lib64/libQt5Core.so.5+0x2da3e8)
    #8 0x4adcd8 in GenericChatroomWidget::chatroomWidgetClicked(GenericChatroomWidget*) /home/abilinski/builds/qTox/_build/qtox_static_autogen/WFD7YQQOTJ/moc_genericchatroomwidget.cpp:270
    #9 0x8d5fb5 in GenericChatroomWidget::mouseReleaseEvent(QMouseEvent*) /home/abilinski/builds/qTox/src/widget/genericchatroomwidget.cpp:172
    #10 0x7ffff4e45e7d in QWidget::event(QEvent*) (/lib64/libQt5Widgets.so.5+0x1f0e7d)

SUMMARY: AddressSanitizer: heap-use-after-free /usr/include/qt5/QtWidgets/qwidget.h:883 in QWidget::testAttribute(Qt::WidgetAttribute) const
Shadow bytes around the buggy address:
  0x0c1c8002ede0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c1c8002edf0: fa fa fa fa fa fa fa fa fa fa fa fa fd fd fd fd
  0x0c1c8002ee00: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
  0x0c1c8002ee10: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
  0x0c1c8002ee20: fd fd fd fd fd fd fd fd fd fd fd fd fa fa fa fa
=>0x0c1c8002ee30: fa fa fa fa fd fd fd fd fd[fd]fd fd fd fd fd fd
  0x0c1c8002ee40: fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa fa
  0x0c1c8002ee50: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c1c8002ee60: fd fd fd fd fa fa fa fa fa fa fa fa fd fd fd fd
  0x0c1c8002ee70: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c1c8002ee80: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==11469==ABORTING

Will analyze more tomorrow, but looks like the dialog is being deleted mid-call into show through the QObject::event, which is what causes the crash in QWidget when it's trying to call into that dialog. Still not totally sure where the blame lies.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants