Skip to content

Add a Gitter chat badge to README.md#1

Closed
gitter-badger wants to merge 1 commit intoSlySven:developmentfrom
gitter-badger:gitter-badge
Closed

Add a Gitter chat badge to README.md#1
gitter-badger wants to merge 1 commit intoSlySven:developmentfrom
gitter-badger:gitter-badge

Conversation

@gitter-badger
Copy link
Copy Markdown

SlySven/Mudlet now has a Chat Room on Gitter

@SlySven has just created a chat room. You can visit it here: https://gitter.im/SlySven/Mudlet.

This pull-request adds this badge to your README.md:

![Gitter](https://badges.gitter.im/Join Chat.svg)

Happy chatting.

PS: Click here if you would prefer not to receive automatic pull-requests from Gitter in future.

SlySven pushed a commit that referenced this pull request Mar 23, 2015
SlySven added a commit that referenced this pull request Apr 15, 2016
…ata()

(where XXXX is Room or Area!)

I have realised that the functionality could usefully be included in the
existing functions and be utilised by invoking those with NO arguments.
This avoids the addition of yet another pair of functions (and Mudlet
versions WITH this functionality can be detected by script writers by the
fact that existing code will raise an error about a bad argument #1 {being
"nil"} if a new script tries to use the function on an older version.)

Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
SlySven added a commit that referenced this pull request Apr 16, 2016
…ata()

(where XXXX is Room or Area!)

I have realised that the functionality could usefully be included in the
existing functions and be utilised by invoking those with NO arguments.
This avoids the addition of yet another pair of functions (and Mudlet
versions WITH this functionality can be detected by script writers by the
fact that existing code will raise an error about a bad argument #1 {being
"nil"} if a new script tries to use the function on an older version.)

Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
SlySven pushed a commit that referenced this pull request May 6, 2018
Revise: polish up some aspects of AlysCole's PR
SlySven pushed a commit that referenced this pull request May 6, 2018
 - Rebase onto Stephen Lyons's PR #1.
 - When dlgProfilePreferences::slot_logFileNameFormatChange() and
   initWithHost() are called, set lineEdit_logFileName to visible
   depending on the selected option in comboBox_logFileNameFormat.
   The lineEdit should only be visible when comboBox_logFileNameFormat
   is set to 'Named file'.
 - Use QString rather than QDir to take the return value of
   QFileDialog::getExistingDirectory. This will allow us to check
   whether the return value is NULL (which happens when a user
   presses 'Cancel' within the file dialog).
 - When initWithHost() is called, set the text property of
   pushButton_whereToLog to contain the user's current log directory.
   When the button is pushed and another directory selected, set the
   text property to the selected directory, whether or not it is
   saved.
 - Move pushButton_whereToLog->setToolTip(...),
   comboBox_logFileNameFormat->addItem(...), and all lines setting the
   properties of the log options above the call to initWithHost() so
   the adding of Qt properties goes before the properties being set in
   line with the values within Host.
SlySven pushed a commit that referenced this pull request May 24, 2018
Update Contributors outstanding PR
@SlySven SlySven closed this Mar 28, 2019
SlySven added a commit that referenced this pull request Apr 1, 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>
SlySven pushed a commit that referenced this pull request Jun 22, 2020
BugFix: CorTheWin's development branch
SlySven pushed a commit that referenced this pull request Jun 22, 2020
SlySven pushed a commit that referenced this pull request Nov 12, 2023
Change the way the osx installer is created
SlySven added a commit that referenced this pull request Dec 15, 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 Mudlet#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>
SlySven pushed 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.
SlySven pushed a commit that referenced this pull request Dec 4, 2025
…rocessing (Mudlet#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
Mudlet#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>
SlySven pushed a commit that referenced this pull request Dec 4, 2025
…gers (Mudlet#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.
SlySven pushed a commit that referenced this pull request Feb 6, 2026
Mudlet#8694) (Mudlet#8751)

## Summary

Fixes Mudlet#8694 - `table.update` would error when the first table had a
non-table value (number, string, boolean) at a key where the second
table had a table value.

**Example that crashed:**
```lua
table.update({ x = 1 }, { x = { y = 2 } })
-- Error: bad argument #1 to 'pairs' (table expected, got number)
```

**Root cause:** The recursion logic `tbl[k] = table.update(tbl[k] or {},
v)` only checked for nil/false before recursing, not for other non-table
types.

**Fix:** Check `type(existing) == "table"` before passing to recursive
call.

## Test plan

- [x] Added 5 new test cases in `TableUtils_spec.lua`:
  - Replace number with table
  - Replace table with number  
  - Merge nested tables (both tables)
  - Replace string with table
  - Replace boolean with table

- [x] Verified fix works: `luajit -e "dofile('...TableUtils.lua');
print(table.update({x=1}, {x={y=2}}).x.y)"` outputs `2`

## Notes

Tests require running inside Mudlet with `runTests` command (uses Busted
framework loaded by Mudlet).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Vadim Peretokin <vperetokin@hey.com>
SlySven pushed a commit that referenced this pull request Feb 7, 2026
…gers (Mudlet#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)
SlySven pushed a commit that referenced this pull request Feb 7, 2026
Mudlet#8694) (Mudlet#8751)

## Summary

Fixes Mudlet#8694 - `table.update` would error when the first table had a
non-table value (number, string, boolean) at a key where the second
table had a table value.

**Example that crashed:**
```lua
table.update({ x = 1 }, { x = { y = 2 } })
-- Error: bad argument #1 to 'pairs' (table expected, got number)
```

**Root cause:** The recursion logic `tbl[k] = table.update(tbl[k] or {},
v)` only checked for nil/false before recursing, not for other non-table
types.

**Fix:** Check `type(existing) == "table"` before passing to recursive
call.

## Test plan

- [x] Added 5 new test cases in `TableUtils_spec.lua`:
  - Replace number with table
  - Replace table with number
  - Merge nested tables (both tables)
  - Replace string with table
  - Replace boolean with table

- [x] Verified fix works: `luajit -e "dofile('...TableUtils.lua');
print(table.update({x=1}, {x={y=2}}).x.y)"` outputs `2`

## Notes

Tests require running inside Mudlet with `runTests` command (uses Busted
framework loaded by Mudlet).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Vadim Peretokin <vperetokin@hey.com>
(cherry picked from commit c9e560b)
SlySven pushed 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants