Profile keyboard navigation#2
Merged
vadi2 merged 4 commits intoMudlet:developmentfrom Dec 26, 2013
vadi2:development
Merged
Conversation
Profile keyboard navigation
vadi2
referenced
this pull request
in vadi2/Mudlet
Apr 4, 2017
Fixed the use of option values as columns
This was referenced Jul 18, 2017
vadi2
added a commit
that referenced
this pull request
Mar 31, 2020
* Adds an option for variables to be included in searches, which is disabled by default now. This option is in the search menu on the left side of the search bar, positioned with the Case Sensitivity option. * Revise: add "with-variables" icons & persistent storage of search options Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Update copyright stamp #1 * Update copyright date #2 * Trim tooltip to UX standard Co-authored-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
Closed
Chris7
pushed a commit
to Chris7/Mudlet
that referenced
this pull request
Jan 2, 2022
* Adds an option for variables to be included in searches, which is disabled by default now. This option is in the search menu on the left side of the search bar, positioned with the Case Sensitivity option. * Revise: add "with-variables" icons & persistent storage of search options Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Update copyright stamp Mudlet#1 * Update copyright date Mudlet#2 * Trim tooltip to UX standard Co-authored-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
mehulmathur16
pushed a commit
to mehulmathur16/Mudlet
that referenced
this pull request
Feb 16, 2024
…ence-free feat: Take DSN use minidump url
vadi2
added a commit
that referenced
this pull request
Dec 14, 2024
<!-- Keep the title short & concise so anyone non-technical can
understand it,
the title appears in PTB changelogs -->
#### Brief overview of PR changes/additions
Fixes Mudlet crash with IRC open when closing a profile
#### Motivation for adding to Mudlet
Mudlet should never crash
#### Other info (issues closed, discussion etc)
Closes #7293. I'll fix other
cases of `Host* mpHost;` after this PR so we have consistency in the
codebase.
Running the provided test case through
[AddressSanitizer](https://wiki.mudlet.org/w/Compiling_Mudlet#Checking_memory_leaks_.26_other_issues_.28sanitizers.29_3)
revealed that mpHost was being used after it was deleted:
```
=================================================================
==17843==ERROR: AddressSanitizer: heap-use-after-free on address 0x623000025e58 at pc 0x5555560abe75 bp 0x7fffffff7460 sp 0x7fffffff7450
READ of size 8 at 0x623000025e58 thread T0
#0 0x5555560abe74 in QWeakPointer<QObject>::internalData() const /usr/include/x86_64-linux-gnu/qt6/QtCore/qsharedpointer_impl.h:711
#1 0x5555562c15ad in QPointer<dlgIRC>::data() const /usr/include/x86_64-linux-gnu/qt6/QtCore/qpointer.h:77
#2 0x5555562bd715 in QPointer<dlgIRC>::operator dlgIRC*() const /usr/include/x86_64-linux-gnu/qt6/QtCore/qpointer.h:85
#3 0x555556296c13 in dlgIRC::~dlgIRC() /home/vadi/Programs/Mudlet/src/dlgIRC.cpp:109
#4 0x555556296e1f in dlgIRC::~dlgIRC() /home/vadi/Programs/Mudlet/src/dlgIRC.cpp:112
#5 0x7ffff6ba04a0 in QObject::event(QEvent*) (/lib/x86_64-linux-gnu/libQt6Core.so.6+0x1a04a0)
...
```
This helped pinpoint the cause of the crash.
---------
Co-authored-by: Stephen Lyons <slysven@virginmedia.com>
Co-authored-by: Vadim Peretokin <vadi2@users.noreply.github.com>
Closed
vadi2
added a commit
that referenced
this pull request
May 16, 2025
This was referenced Aug 30, 2025
vadi2
added a commit
that referenced
this pull request
Oct 18, 2025
<!-- Keep the title short & concise so anyone non-technical can
understand it,
the title appears in PTB changelogs -->
#### Brief overview of PR changes/additions
Fix
```
Direct leak of 4000 byte(s) in 50 object(s) allocated from:
#0 0x7f21286b61e7 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:99
#1 0x5652d10ed62c in TriggerHighlighter::setTheme(QString const&) (/home/runner/work/Mudlet/Mudlet/src/mudlet+0x202562c)
#2 0x5652d10ecba7 in TriggerHighlighter::TriggerHighlighter(QTextDocument*) (/home/runner/work/Mudlet/Mudlet/src/mudlet+0x2024ba7)
#3 0x5652d0998ef2 in SingleLineTextEdit::SingleLineTextEdit(QWidget*) (/home/runner/work/Mudlet/Mudlet/src/mudlet+0x18d0ef2)
#4 0x5652d05f581a in Ui_trigger_pattern_edit::setupUi(QWidget*) (/home/runner/work/Mudlet/Mudlet/src/mudlet+0x152d81a)
#5 0x5652d05f2792 in dlgTriggerPatternEdit::dlgTriggerPatternEdit(QWidget*) (/home/runner/work/Mudlet/Mudlet/src/mudlet+0x152a792)
#6 0x5652d044b2a2 in dlgTriggerEditor::dlgTriggerEditor(Host*) (/home/runner/work/Mudlet/Mudlet/src/mudlet+0x13832a2)
#7 0x5652d08479a9 in mudlet::addConsoleForNewHost(Host*) (/home/runner/work/Mudlet/Mudlet/src/mudlet+0x177f9a9)
#8 0x5652d086efcb in mudlet::slot_connectionDialogueFinished(QString const&, bool) (/home/runner/work/Mudlet/Mudlet/src/mudlet+0x17a6fcb)
```
#### Motivation for adding to Mudlet
Better app quality
#### Other info (issues closed, discussion etc)
Discovered when running Mudlet with cmake.
vadi2
added a commit
that referenced
this pull request
Nov 26, 2025
…rocessing (#8571) <!-- Keep the title short & concise so anyone non-technical can understand it, the title appears in PTB changelogs --> #### Brief overview of PR changes/additions Fix: heap-use-after-free when cleanup runs during alias/trigger/key processing #### Motivation for adding to Mudlet Fixes crash when running #8559 (comment) benchmark on Linux. #### Other info (issues closed, discussion etc) ==617553==ERROR: AddressSanitizer: heap-use-after-free on address 0x51200086e6d0 at pc 0x589b650367f6 bp 0x7ffc44dbc700 sp 0x7ffc44dbc6f8 READ of size 8 at 0x51200086e6d0 thread T0 #0 0x589b650367f5 in Tree<TAlias>::isActive() const (/home/vadi/Programs/Mudlet/build/src/mudlet+0xe8a7f5) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #1 0x589b65d81408 in TAlias::match(QString const&) (/home/vadi/Programs/Mudlet/build/src/mudlet+0x1bd5408) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #2 0x589b6560c156 in AliasUnit::processDataStream(QString const&) (/home/vadi/Programs/Mudlet/build/src/mudlet+0x1460156) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #3 0x589b65c872b4 in Host::send(QString, bool, bool) (/home/vadi/Programs/Mudlet/build/src/mudlet+0x1adb2b4) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #4 0x589b65d96517 in TCommandLine::enterCommand(QKeyEvent*) (/home/vadi/Programs/Mudlet/build/src/mudlet+0x1bea517) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #5 0x589b65d93095 in TCommandLine::event(QEvent*) (/home/vadi/Programs/Mudlet/build/src/mudlet+0x1be7095) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #6 0x7ac668391c8a in QApplicationPrivate::notify_helper(QObject*, QEvent*) /home/qt/work/qt/qtbase/src/widgets/kernel/qapplication.cpp:3307:31 #7 0x7ac66839b2f0 in QApplication::notify(QObject*, QEvent*) /home/qt/work/qt/qtbase/src/widgets/kernel/qapplication.cpp:2725:39 #8 0x7ac668b83f7f in QCoreApplication::notifyInternal2(QObject*, QEvent*) /home/qt/work/qt/qtbase/src/corelib/kernel/qcoreapplication.cpp:1109:24 #9 0x7ac66840cc0b in QWidgetWindow::event(QEvent*) /home/qt/work/qt/qtbase/src/widgets/kernel/qwidgetwindow.cpp:285:23 #10 0x7ac668391c8a in QApplicationPrivate::notify_helper(QObject*, QEvent*) /home/qt/work/qt/qtbase/src/widgets/kernel/qapplication.cpp:3307:31 #11 0x7ac668b83f7f in QCoreApplication::notifyInternal2(QObject*, QEvent*) /home/qt/work/qt/qtbase/src/corelib/kernel/qcoreapplication.cpp:1109:24 #12 0x7ac6677ee8e2 in QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyEvent*) /home/qt/work/qt/qtbase/src/gui/kernel/qguiapplication.cpp:2609:46 #13 0x7ac655cf9a04 in QIBusPlatformInputContext::filterEventFinished(QDBusPendingCallWatcher*) /home/qt/work/qt/qtbase/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp:523:57 #14 0x7ac668be8b74 in QtPrivate::QSlotObjectBase::call(QObject*, void**) /home/qt/work/qt/qtbase/src/corelib/kernel/qobjectdefs_impl.h:461:57 #15 0x7ac668be8b74 in void doActivate<false>(QObject*, int, void**) /home/qt/work/qt/qtbase/src/corelib/kernel/qobject.cpp:4255:30 #16 0x7ac6671e5142 in void QMetaObject::activate<void, QDBusPendingCallWatcher*>(QObject*, QMetaObject const*, int, void*, QDBusPendingCallWatcher* const&) /home/qt/work/qt/qtbase/src/corelib/kernel/qobjectdefs.h:319:17 #17 0x7ac6671e5142 in QDBusPendingCallWatcher::finished(QDBusPendingCallWatcher*) /home/qt/work/qt/qtbase_build/src/dbus/DBus_autogen/include/moc_qdbuspendingcall.cpp:137:32 #18 0x7ac668bdd56b in QObject::event(QEvent*) /home/qt/work/qt/qtbase/src/corelib/kernel/qobject.cpp:1411:31 #19 0x7ac668391c8a in QApplicationPrivate::notify_helper(QObject*, QEvent*) /home/qt/work/qt/qtbase/src/widgets/kernel/qapplication.cpp:3307:31 #20 0x7ac668b83f7f in QCoreApplication::notifyInternal2(QObject*, QEvent*) /home/qt/work/qt/qtbase/src/corelib/kernel/qcoreapplication.cpp:1109:24 #21 0x7ac668b879e4 in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) /home/qt/work/qt/qtbase/src/corelib/kernel/qcoreapplication.cpp:1904:36 #22 0x7ac668e7d416 in postEventSourceDispatch /home/qt/work/qt/qtbase/src/corelib/kernel/qeventdispatcher_glib.cpp:246:39 #23 0x7ac6667145c4 (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x5d5c4) (BuildId: 1eb6131419edb83b2178b682829a6913cf682d75) #24 0x7ac666773736 (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0xbc736) (BuildId: 1eb6131419edb83b2178b682829a6913cf682d75) #25 0x7ac666713a62 in g_main_context_iteration (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x5ca62) (BuildId: 1eb6131419edb83b2178b682829a6913cf682d75) #26 0x7ac668e7caad in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) /home/qt/work/qt/qtbase/src/corelib/kernel/qeventdispatcher_glib.cpp:399:43 #27 0x7ac668b9002a in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) /home/qt/work/qt/qtbase/src/corelib/kernel/qeventloop.cpp:186:22 #28 0x7ac668b8ba59 in QCoreApplication::exec() /home/qt/work/qt/qtbase/src/corelib/kernel/qcoreapplication.cpp:1452:36 #29 0x589b64ab0675 in main (/home/vadi/Programs/Mudlet/build/src/mudlet+0x904675) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #30 0x7ac66602a1c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16 #31 0x7ac66602a28a in __libc_start_main csu/../csu/libc-start.c:360:3 #32 0x589b649c1d04 in _start (/home/vadi/Programs/Mudlet/build/src/mudlet+0x815d04) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) 0x51200086e6d0 is located 16 bytes inside of 296-byte region [0x51200086e6c0,0x51200086e7e8) freed by thread T0 here: #0 0x589b64a9b9f1 in operator delete(void*) (/home/vadi/Programs/Mudlet/build/src/mudlet+0x8ef9f1) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #1 0x589b65d80711 in TAlias::~TAlias() (/home/vadi/Programs/Mudlet/build/src/mudlet+0x1bd4711) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #2 0x589b6560eefc in AliasUnit::doCleanup() (/home/vadi/Programs/Mudlet/build/src/mudlet+0x1462efc) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #3 0x589b65c8e88d in Host::incomingStreamProcessor(QString const&, int) (/home/vadi/Programs/Mudlet/build/src/mudlet+0x1ae288d) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #4 0x589b651b73b5 in TMainConsole::runTriggers(int) (/home/vadi/Programs/Mudlet/build/src/mudlet+0x100b3b5) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #5 0x589b64e39c4b in TBuffer::commitLine(char, unsigned long&) (/home/vadi/Programs/Mudlet/build/src/mudlet+0xc8dc4b) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #6 0x589b64e28d4e in TBuffer::translateToPlainText(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>&, bool) (/home/vadi/Programs/Mudlet/build/src/mudlet+0xc7cd4e) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #7 0x589b651b638d in TMainConsole::printOnDisplay(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>&, bool) (/home/vadi/Programs/Mudlet/build/src/mudlet+0x100a38d) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #8 0x589b64f9ed5b in TLuaInterpreter::feedTriggers(lua_State*) (/home/vadi/Programs/Mudlet/build/src/mudlet+0xdf2d5b) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #9 0x7ac66942ffa0 in luaD_precall /build/lua5.1-rMDsVj/lua5.1-5.1.5/src/ldo.c:320:10 #10 0x7ac66943ad7a in luaV_execute /build/lua5.1-rMDsVj/lua5.1-5.1.5/src/lvm.c:591:17 #11 0x7ac66942e96c in luaD_call /build/lua5.1-rMDsVj/lua5.1-5.1.5/src/ldo.c:378:5 #12 0x7ac66942af70 in luaD_rawrunprotected /build/lua5.1-rMDsVj/lua5.1-5.1.5/src/ldo.c:116:3 #13 0x7ac66942bb94 in luaD_pcall /build/lua5.1-rMDsVj/lua5.1-5.1.5/src/ldo.c:464:12 #14 0x7ac66942bce0 in lua_pcall /build/lua5.1-rMDsVj/lua5.1-5.1.5/src/lapi.c:821:12 #15 0x589b64fd65f1 in TLuaInterpreter::call(QString const&, QString const&, bool) (/home/vadi/Programs/Mudlet/build/src/mudlet+0xe2a5f1) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #16 0x589b65d84d31 in TAlias::execute() (/home/vadi/Programs/Mudlet/build/src/mudlet+0x1bd8d31) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #17 0x589b65d84577 in TAlias::match(QString const&) (/home/vadi/Programs/Mudlet/build/src/mudlet+0x1bd8577) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #18 0x589b6560c156 in AliasUnit::processDataStream(QString const&) (/home/vadi/Programs/Mudlet/build/src/mudlet+0x1460156) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #19 0x589b65c872b4 in Host::send(QString, bool, bool) (/home/vadi/Programs/Mudlet/build/src/mudlet+0x1adb2b4) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #20 0x589b65d96517 in TCommandLine::enterCommand(QKeyEvent*) (/home/vadi/Programs/Mudlet/build/src/mudlet+0x1bea517) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #21 0x589b65d93095 in TCommandLine::event(QEvent*) (/home/vadi/Programs/Mudlet/build/src/mudlet+0x1be7095) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #22 0x7ac668391c8a in QApplicationPrivate::notify_helper(QObject*, QEvent*) /home/qt/work/qt/qtbase/src/widgets/kernel/qapplication.cpp:3307:31 previously allocated by thread T0 here: #0 0x589b64a9b171 in operator new(unsigned long) (/home/vadi/Programs/Mudlet/build/src/mudlet+0x8ef171) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #1 0x589b6500f595 in TLuaInterpreter::startTempAlias(QString const&, QString const&) (/home/vadi/Programs/Mudlet/build/src/mudlet+0xe63595) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #2 0x589b6512c41d in TLuaInterpreter::tempAlias(lua_State*) (/home/vadi/Programs/Mudlet/build/src/mudlet+0xf8041d) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #3 0x7ac66942ffa0 in luaD_precall /build/lua5.1-rMDsVj/lua5.1-5.1.5/src/ldo.c:320:10 #4 0x7ac66943ad7a in luaV_execute /build/lua5.1-rMDsVj/lua5.1-5.1.5/src/lvm.c:591:17 #5 0x7ac66942e96c in luaD_call /build/lua5.1-rMDsVj/lua5.1-5.1.5/src/ldo.c:378:5 #6 0x7ac66942af70 in luaD_rawrunprotected /build/lua5.1-rMDsVj/lua5.1-5.1.5/src/ldo.c:116:3 #7 0x7ac66942bb94 in luaD_pcall /build/lua5.1-rMDsVj/lua5.1-5.1.5/src/ldo.c:464:12 #8 0x7ac66942bce0 in lua_pcall /build/lua5.1-rMDsVj/lua5.1-5.1.5/src/lapi.c:821:12 #9 0x589b64fd65f1 in TLuaInterpreter::call(QString const&, QString const&, bool) (/home/vadi/Programs/Mudlet/build/src/mudlet+0xe2a5f1) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #10 0x589b65d84d31 in TAlias::execute() (/home/vadi/Programs/Mudlet/build/src/mudlet+0x1bd8d31) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #11 0x589b65d84577 in TAlias::match(QString const&) (/home/vadi/Programs/Mudlet/build/src/mudlet+0x1bd8577) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #12 0x589b6560c156 in AliasUnit::processDataStream(QString const&) (/home/vadi/Programs/Mudlet/build/src/mudlet+0x1460156) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #13 0x589b65c872b4 in Host::send(QString, bool, bool) (/home/vadi/Programs/Mudlet/build/src/mudlet+0x1adb2b4) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #14 0x589b65d96517 in TCommandLine::enterCommand(QKeyEvent*) (/home/vadi/Programs/Mudlet/build/src/mudlet+0x1bea517) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #15 0x589b65d93095 in TCommandLine::event(QEvent*) (/home/vadi/Programs/Mudlet/build/src/mudlet+0x1be7095) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) #16 0x7ac668391c8a in QApplicationPrivate::notify_helper(QObject*, QEvent*) /home/qt/work/qt/qtbase/src/widgets/kernel/qapplication.cpp:3307:31 SUMMARY: AddressSanitizer: heap-use-after-free (/home/vadi/Programs/Mudlet/build/src/mudlet+0xe8a7f5) (BuildId: c98a5e4208b6daa52aa1b083c4ee6c4ab4552cc4) in Tree<TAlias>::isActive() const Shadow bytes around the buggy address: 0x51200086e400: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x51200086e480: fd fd fd fd fd fd fd fd fd fd fd fd fd fa fa fa 0x51200086e500: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd 0x51200086e580: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x51200086e600: fd fd fd fd fd fd fd fd fd fd fd fd fd fa fa fa =>0x51200086e680: fa fa fa fa fa fa fa fa fd fd[fd]fd fd fd fd fd 0x51200086e700: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x51200086e780: fd fd fd fd fd fd fd fd fd fd fd fd fd fa fa fa 0x51200086e800: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd 0x51200086e880: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x51200086e900: fd fd fd fd fd fd fd fd fd fd fd fd fd fa fa fa 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 ==617553==ABORTING Co-authored-by: Vadim Peretokin <vadi2@users.noreply.github.com>
vadi2
pushed a commit
that referenced
this pull request
Nov 26, 2025
…gers (#8567) #### Brief overview of PR changes/additions Fixed a heap-use-after-free crash in TBuffer destructor by converting the raw `mTagWatchdog` pointer to `std::unique_ptr<QTimer>` and implementing proper copy constructor and copy assignment operator. #### Motivation for adding to Mudlet The crash occurred when closing a profile (e.g., using "Close Profile" menu item on Medievia MUD) that had been actively receiving data and running triggers. The issue was caused by TBuffer objects being copied without properly handling the ownership of the `mTagWatchdog` QTimer. When temporary TBuffer objects were created during copy operations (like in `TConsole::copy()`), both the original and copied instances shared the same QTimer pointer. When one instance was destroyed, it deleted the timer, leaving the other with a dangling pointer that caused a crash on subsequent destruction. AddressSanitizer trace showed: ``` ERROR: AddressSanitizer: heap-use-after-free on address 0x602000915670 READ of size 8 at 0x602000915670 thread T0 #0 in TBuffer::TBuffer()+0x88 #1 in TBuffer::TBuffer()+0x18 #2 in TMainConsole::~TMainConsole()+0x5a8 ``` The fix ensures each TBuffer instance owns its own QTimer through a unique_ptr, preventing double-deletion and use-after-free errors. #### Other info (issues closed, discussion etc) This resolves crashes that occurred during profile shutdown when the copy() Lua function was used in triggers processing incoming game data.
vadi2
pushed a commit
that referenced
this pull request
Nov 26, 2025
…gers (#8567) #### Brief overview of PR changes/additions Fixed a heap-use-after-free crash in TBuffer destructor by converting the raw `mTagWatchdog` pointer to `std::unique_ptr<QTimer>` and implementing proper copy constructor and copy assignment operator. #### Motivation for adding to Mudlet The crash occurred when closing a profile (e.g., using "Close Profile" menu item on Medievia MUD) that had been actively receiving data and running triggers. The issue was caused by TBuffer objects being copied without properly handling the ownership of the `mTagWatchdog` QTimer. When temporary TBuffer objects were created during copy operations (like in `TConsole::copy()`), both the original and copied instances shared the same QTimer pointer. When one instance was destroyed, it deleted the timer, leaving the other with a dangling pointer that caused a crash on subsequent destruction. AddressSanitizer trace showed: ``` ERROR: AddressSanitizer: heap-use-after-free on address 0x602000915670 READ of size 8 at 0x602000915670 thread T0 #0 in TBuffer::TBuffer()+0x88 #1 in TBuffer::TBuffer()+0x18 #2 in TMainConsole::~TMainConsole()+0x5a8 ``` The fix ensures each TBuffer instance owns its own QTimer through a unique_ptr, preventing double-deletion and use-after-free errors. #### Other info (issues closed, discussion etc) This resolves crashes that occurred during profile shutdown when the copy() Lua function was used in triggers processing incoming game data. (cherry picked from commit d56c6c2)
vadi2
added a commit
that referenced
this pull request
Apr 8, 2026
<!-- Keep the title short & concise so anyone non-technical can
understand it,
the title appears in PTB changelogs -->
#### Brief overview of PR changes/additions
Fixes memory leaks from playing sounds, opening the room exits dialog,
opening Preferences, right-clicking the console, connecting to MUDs with
compression, and viewing changelogs
#### Motivation for adding to Mudlet
Better memory management.
#### Other info (issues closed, discussion etc)
##### 3. TMediaPlayer destructor leaks TMediaPlaylist + QAudioOutput
```
playSoundFile() [TLuaInterpreterMedia.cpp:703]
→ TMedia::playMedia() [TMedia.cpp:47] → play() [TMedia.cpp:1485]
→ getMediaPlayer() [TMedia.cpp:1150]
→ make_shared<TMediaPlayer>(mpHost, mediaData) [TMedia.cpp:1193]
→ constructor: mPlaylist(new TMediaPlaylist) ← LEAK #1 [TMedia.h:47]
→ constructor: setAudioOutput(new QAudioOutput()) ← LEAK #2 [TMedia.h:50]
→ updateMediaPlayerList() [TMedia.cpp:1102]
→ purgeStoppedMediaPlayers() [TMedia.cpp:1056] (when list > 25)
→ shared_ptr destroyed → ~TMediaPlayer() = default ← NEVER DELETES [TMedia.h:52]
```
##### 6. dlgRoomExits TExit objects never freed
```
Right-click room → "Set exits..." [RoomContextMenuHandler.cpp:196]
→ T2DMap::slot_setExits() [T2DMap.cpp:4271]
→ new dlgRoomExits(...) [T2DMap.cpp:4278] + setAttribute(WA_DeleteOnClose) [T2DMap.cpp:4280]
→ init() [dlgRoomExits.cpp:279]
→ initExit() x12 [dlgRoomExits.cpp:1633-1775]
→ originalExits[dir] = makeExitFromControls(dir) [dlgRoomExits.cpp:1599]
→ new TExit() [dlgRoomExits.cpp:1968] ← ALLOCATED
→ new TExit() per special exit [dlgRoomExits.cpp:1782] → originalSpecialExits[dir] [line 1848]
User closes → ~dlgRoomExits() [dlgRoomExits.cpp:285] ← EMPTY, never deletes TExit objects
```
##### 7. dlgProfilePreferences QKeySequence* leak (no destructor)
```
mudlet::showOptionsDialog() [mudlet.cpp:3578]
→ new dlgProfilePreferences(this, pHost) [mudlet.cpp:3585]
→ setAttribute(WA_DeleteOnClose) [mudlet.cpp:3603]
→ constructor loop [dlgProfilePreferences.cpp:1394-1399]:
new QKeySequence(*pHost->profileShortcuts.value(key)) [line 1398]
currentShortcuts.insert(key, sequence) [line 1399] ← 17 raw pointers stored
User closes → WA_DeleteOnClose triggers delete
→ implicit ~dlgProfilePreferences() ← NO DESTRUCTOR EXISTS
→ QMap destroyed, pointer values NOT deleted
```
##### 10. ctelnet missing inflateEnd in destructor
```
Server sends WILL COMPRESS2 → processSocketData [ctelnet.cpp:4876-4880]
→ mNeedDecompression = true → initStreamDecompressor()
→ inflateInit(&mZstream) [ctelnet.cpp:4514] ← allocates ~256KB
Connection drops → slot_socketDisconnected() [ctelnet.cpp:627]
→ mNeedDecompression = false [line 663] ← NO inflateEnd()
→ reset() [line 664] ← NO inflateEnd()
→ ~cTelnet() [line 158] ← NO inflateEnd()
(only inflateEnd is in decompressBuffer:4532, on Z_STREAM_END from server)
```
##### 11. ctelnet QNetworkReply leak on file error paths
```
slot_replyFinished() [ctelnet.cpp:1365]
→ reply->error() == NoError [line 1398]
→ file.open() fails [line 1400] → return ← LEAK (no reply->deleteLater())
→ file.commit() fails [line 1409] → return ← LEAK (no reply->deleteLater())
(compare: error path at line 1393 correctly calls reply->deleteLater())
```
##### 15. TTextEdit QAction accumulation (5-10 per right-click)
```
Right-click on console → mouseReleaseEvent [TTextEdit.cpp:2287]
→ new QAction(tr("Copy"), this) [line 2374] ← parented to TTextEdit, not QMenu
→ new QAction(tr("Copy HTML"), this) [line 2385]
→ new QAction(tr("Copy as image"), this) [line 2389]
→ new QAction(tr("Select all"), this) [line 2392]
→ new QAction(tr("Search on %1"), this) [line 2397]
→ (+ conditional actions at 2416, 2434, 2438, 2448, 2465)
→ popup = new QMenu(this) + WA_DeleteOnClose [line 2406-2407]
→ Menu closes → QMenu deleted, but QActions survive as TTextEdit children ← ACCUMULATE
```
##### 17. Updater changelog dialogs leaked
```
Help → Show changelog → Updater::showChangelog() [updater.cpp:202]
→ new dblsqd::UpdateDialog(feed, ...) ← no parent [line 202]
→ changelogDialog->show() [line 204] ← non-blocking, pointer lost at scope end
(no WA_DeleteOnClose set; same at showFullChangelog:218)
```
##### 20. ModernGLWidget mTexCoordBuffer.destroy() missing
```
initializeGL() → setupBuffers() [modern_glwidget.cpp:146]
→ mTexCoordBuffer.create() [line 183]
~ModernGLWidget() → cleanup() [line 70]
→ mVertexBuffer.destroy() [line 78] ✓
→ mColorBuffer.destroy() [line 79] ✓
→ mNormalBuffer.destroy() [line 80] ✓
→ mIndexBuffer.destroy() [line 81] ✓
→ mInstanceBuffer.destroy() [line 82] ✓
→ mTexCoordBuffer.destroy() ← MISSING between lines 82 and 83
→ mVAO.destroy() [line 83] ✓
```
##### 21. dlgComposer context menu + Hunspell suggestions
```
Right-click in composer → slot_contextMenu() [dlgComposer.cpp:226]
→ createStandardContextMenu() [line 228] ← returns new QMenu*, no parent
→ fillSpellCheckList() [line 233] → Hunspell_suggest() [line 331,335] ← allocates lists
→ popup->popup() [line 237] ← non-blocking, pointer lost
← QMenu leaked (no WA_DeleteOnClose, no deleteLater)
← If dismissed without selection: Hunspell_free_list() never called [only at line 468,472]
```
##### 22-24. Lower-impact (also in this branch)
```
dlgColorTrigger after exec() [dlgTriggerEditor.cpp:12469,12532]:
→ new dlgColorTrigger(this, ...) → exec() → no delete pD
Hunspell shared dictionary [mudlet.cpp:4768]:
→ mpHunspell_sharedDictionary = nullptr ← missing Hunspell_destroy() before
ExitsTreeWidget takeTopLevelItem [exitstreewidget.cpp:45]:
→ takeTopLevelItem(indexOfTopLevelItem(pItem)) ← return value discarded, never deleted
```
---------
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.