Skip to content

Commit b48d77b

Browse files
wjlafranceclaude
andcommitted
Fix null race conditions in GameState.Close with local captures
ActiveChannel, ActiveClan, ActiveAccount, and GameAd could be set to null by another thread between the null check and the method call. Use local variable capture to prevent NullReferenceException. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent dbef886 commit b48d77b

1 file changed

Lines changed: 14 additions & 10 deletions

File tree

src/Atlasd/Battlenet/Protocols/Game/GameState.cs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public enum LogonTypes : UInt32
1919
NLS = 2,
2020
};
2121

22-
private bool IsDisposing = false;
22+
private volatile bool IsDisposing = false;
2323

2424
public ClientState Client { get; protected set; }
2525

@@ -126,26 +126,29 @@ public static bool CanStatstringUpdate(Product.ProductCode code)
126126
public void Close()
127127
{
128128
// Remove this GameState from ActiveChannel
129-
if (ActiveChannel != null)
129+
var channel = ActiveChannel;
130+
if (channel != null)
130131
{
131-
ActiveChannel.RemoveUser(this); // will change this.ActiveChannel to null.
132+
channel.RemoveUser(this); // will change this.ActiveChannel to null.
132133
}
133134

134135
// Notify clan members
135-
if (ActiveClan != null)
136+
var clan = ActiveClan;
137+
if (clan != null)
136138
{
137-
ActiveClan.WriteStatusChange(this, false); // offline
139+
clan.WriteStatusChange(this, false); // offline
138140
}
139141

140142
// Update keys of ActiveAccount
141-
if (ActiveAccount != null)
143+
var account = ActiveAccount;
144+
if (account != null)
142145
{
143-
ActiveAccount.Set(Account.LastLogoffKey, DateTime.Now);
146+
account.Set(Account.LastLogoffKey, DateTime.Now);
144147

145-
var timeLogged = (UInt32)ActiveAccount.Get(Account.TimeLoggedKey);
148+
var timeLogged = (UInt32)account.Get(Account.TimeLoggedKey);
146149
var diff = DateTime.Now - ConnectedTimestamp;
147150
timeLogged += (UInt32)Math.Round(diff.TotalSeconds);
148-
ActiveAccount.Set(Account.TimeLoggedKey, timeLogged);
151+
account.Set(Account.TimeLoggedKey, timeLogged);
149152
}
150153

151154
// Remove this OnlineName from ActiveAccounts and ActiveGameStates
@@ -156,7 +159,8 @@ public void Close()
156159
}
157160

158161
// Remove this GameAd
159-
if (GameAd != null && GameAd.RemoveClient(this)) GameAd = null;
162+
var gameAd = GameAd;
163+
if (gameAd != null && gameAd.RemoveClient(this)) GameAd = null;
160164
}
161165

162166
public void Dispose() /* part of IDisposable */

0 commit comments

Comments
 (0)