fix(chat): release Utf8String when linkshell check rejects channel
Cherry-pick from ChatTwo upstream f35b7d3 (Infiziert90, 2026-05-12). Chat.SetChannel allocates a native Utf8String for the target name and then runs a validity check. The previous early return on an invalid linkshell skipped Dtor and leaked the native allocation; every invalid linkshell switch added one Utf8String to the unmanaged heap. - Renamed ValidAnyLinkshell to IsChannelOrExistingLinkshell so the call-site reads naturally. - Wrapped ChangeChatChannel in the validity check instead of early-returning. Dtor now runs on every path. - ChatLogWindow follows the rename at its single call-site.
This commit is contained in:
@@ -423,16 +423,24 @@ internal sealed unsafe class Chat : IDisposable
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if channel is valid (non-linkshell or existing linkshell)
|
// ---------------------------------------------------------------
|
||||||
internal static bool ValidAnyLinkshell(InputChannel channel)
|
// Cherry-picked from ChatTwo upstream f35b7d3 (Infiziert90, 2026-05-12)
|
||||||
|
// - Renamed ValidAnyLinkshell -> IsChannelOrExistingLinkshell. The
|
||||||
|
// name now states intent: returns true for any non-linkshell
|
||||||
|
// channel, or a linkshell index that actually exists.
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
internal static bool IsChannelOrExistingLinkshell(InputChannel channel)
|
||||||
{
|
{
|
||||||
var idx = channel.LinkshellIndex();
|
var idx = channel.LinkshellIndex();
|
||||||
if (idx == uint.MaxValue || channel.IsExtraChatLinkshell())
|
if (idx == uint.MaxValue || channel.IsExtraChatLinkshell())
|
||||||
return true;
|
return true;
|
||||||
if (channel.IsLinkshell() && ValidLinkshell(idx))
|
|
||||||
return true;
|
if (channel.IsLinkshell())
|
||||||
if (channel.IsCrossLinkshell() && ValidCrossLinkshell(idx))
|
return ValidLinkshell(idx);
|
||||||
return true;
|
|
||||||
|
if (channel.IsCrossLinkshell())
|
||||||
|
return ValidCrossLinkshell(idx);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -531,12 +539,17 @@ internal sealed unsafe class Chat : IDisposable
|
|||||||
if (idx == uint.MaxValue)
|
if (idx == uint.MaxValue)
|
||||||
idx = 0;
|
idx = 0;
|
||||||
|
|
||||||
if (!ValidAnyLinkshell(channel))
|
// ---------------------------------------------------------------
|
||||||
return;
|
// Cherry-picked from ChatTwo upstream f35b7d3 (Infiziert90, 2026-05-12)
|
||||||
|
// - Wrap ChangeChatChannel in the validity check instead of
|
||||||
|
// early-returning. The previous early return skipped Dtor and
|
||||||
|
// leaked the native Utf8String allocated a few lines above.
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
if (IsChannelOrExistingLinkshell(channel))
|
||||||
RaptureShellModule
|
RaptureShellModule
|
||||||
.Instance()
|
.Instance()
|
||||||
->ChangeChatChannel(tellTarget != null ? 17 : (int)channel, idx, target, true);
|
->ChangeChatChannel(tellTarget != null ? 17 : (int)channel, idx, target, true);
|
||||||
|
|
||||||
target->Dtor(true);
|
target->Dtor(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -272,7 +272,10 @@ public sealed class ChatLogWindow : Window
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetChannel == null || !GameFunctions.Chat.ValidAnyLinkshell(targetChannel.Value))
|
if (
|
||||||
|
targetChannel == null
|
||||||
|
|| !GameFunctions.Chat.IsChannelOrExistingLinkshell(targetChannel.Value)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
Plugin.Log.Warning(
|
Plugin.Log.Warning(
|
||||||
$"Channel was set to an invalid value '{targetChannel}', ignoring"
|
$"Channel was set to an invalid value '{targetChannel}', ignoring"
|
||||||
|
|||||||
Reference in New Issue
Block a user