fix(battle-node): harden SIO parse + narrow Matched OppoId/Seed to int
#3: SocketIoFrame.Parse now range-checks the packet type char (was unchecked cast — any char outside 0-6 produced an undefined enum value) and uses int.TryParse for ack-id (was int.Parse — a >10-digit ack-id threw OverflowException, tearing down the WS mid-game). Both now throw ArgumentException consistently. The read loop in RealParticipant wraps both EIO and SIO parse calls with try-catch so a malformed frame is logged and skipped instead of killing the battle. #4: MatchedSelfInfo/MatchedOppoInfo OppoId and Seed narrowed from long to int. The client reads both with Convert.ToInt32 inside a swallowing try/catch — any value > int.MaxValue silently dropped the Matched event, preventing the battle from starting. Seed was already int-range (BattleSeeds.Stable returns int); OppoId (viewer ID) is ~847M in captures, well under int.MaxValue. The narrowing cast now happens explicitly in ServerBattleFrames.BuildMatched at the wire boundary. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -52,7 +52,10 @@ public sealed class SocketIoFrame
|
||||
if (string.IsNullOrEmpty(raw))
|
||||
throw new ArgumentException("Empty SIO payload", nameof(raw));
|
||||
|
||||
var type = (SocketIoPacketType)(raw[0] - '0');
|
||||
var typeChar = raw[0];
|
||||
if (typeChar < '0' || typeChar > '6')
|
||||
throw new ArgumentException($"Invalid SIO type char '{typeChar}'", nameof(raw));
|
||||
var type = (SocketIoPacketType)(typeChar - '0');
|
||||
var cursor = 1;
|
||||
|
||||
var attachmentCount = 0;
|
||||
@@ -84,7 +87,9 @@ public sealed class SocketIoFrame
|
||||
{
|
||||
var start = cursor;
|
||||
while (cursor < raw.Length && char.IsDigit(raw[cursor])) cursor++;
|
||||
ackId = int.Parse(raw.AsSpan(start, cursor - start));
|
||||
if (!int.TryParse(raw.AsSpan(start, cursor - start), out var parsedAckId))
|
||||
throw new ArgumentException("SIO ack-id overflows int32", nameof(raw));
|
||||
ackId = parsedAckId;
|
||||
}
|
||||
|
||||
var argsJson = cursor < raw.Length ? raw.Substring(cursor) : string.Empty;
|
||||
|
||||
Reference in New Issue
Block a user