fix: tighten resource-leak and null-deref hot spots
Three pre-existing upstream defects flagged by CodeRabbit, fixed in the v1.0.0 standalone cut where we own the codebase: - Ipc/ExtraChat.cs Dispose now unsubscribes all three IPC subscriptions (OverrideChannelGate, ChannelCommandColoursGate, ChannelNamesGate) instead of only the first; previously the latter two leaked their subscriptions on every plugin reload - GameFunctions/Types/TellTarget.cs FromTarget guards against a zero IPlayerCharacter.Address before dereferencing the unsafe Character* cast; previously a missing/destroyed target object would crash the game on /tell construction - GameFunctions/GameFunctions.cs ResolveTextCommandPlaceholderDetour null-checks the Hook reference before calling .Original instead of using the null-forgiving operator; defensive guard for teardown races
This commit is contained in:
@@ -249,9 +249,15 @@ internal unsafe class GameFunctions : IDisposable
|
||||
|
||||
private nint ResolveTextCommandPlaceholderDetour(nint a1, byte* placeholderText, byte a3, byte a4)
|
||||
{
|
||||
// The detour is only invoked through the hook, so the hook should
|
||||
// never be null here, but the nullable field declaration forces us
|
||||
// to handle the theoretical race during teardown.
|
||||
if (ResolveTextCommandPlaceholderHook is null)
|
||||
return nint.Zero;
|
||||
|
||||
var placeholder = MemoryHelper.ReadStringNullTerminated((nint) placeholderText);
|
||||
if (ReplacementName == null || placeholder != Placeholder)
|
||||
return ResolveTextCommandPlaceholderHook!.Original(a1, placeholderText, a3, a4);
|
||||
return ResolveTextCommandPlaceholderHook.Original(a1, placeholderText, a3, a4);
|
||||
|
||||
MemoryHelper.WriteString(PlaceholderNamePtr, ReplacementName);
|
||||
ReplacementName = null;
|
||||
|
||||
@@ -30,6 +30,9 @@ public class TellTarget
|
||||
|
||||
public unsafe void FromTarget(IPlayerCharacter target)
|
||||
{
|
||||
if (target.Address == nint.Zero)
|
||||
return;
|
||||
|
||||
Name = target.Name.TextValue;
|
||||
World = target.HomeWorld.RowId;
|
||||
ContentId = ((Character*)target.Address)->ContentId;
|
||||
|
||||
@@ -49,6 +49,8 @@ public sealed class ExtraChat : IDisposable
|
||||
public void Dispose()
|
||||
{
|
||||
OverrideChannelGate.Unsubscribe(OnOverrideChannel);
|
||||
ChannelCommandColoursGate.Unsubscribe(OnChannelCommandColours);
|
||||
ChannelNamesGate.Unsubscribe(OnChannelNames);
|
||||
}
|
||||
|
||||
private void OnOverrideChannel(OverrideInfo info)
|
||||
|
||||
Reference in New Issue
Block a user