diff --git a/Source/ACE.Server/Network/ClientMessage.cs b/Source/ACE.Server/Network/ClientMessage.cs
index 13dfba8282..c7f4be3afe 100644
--- a/Source/ACE.Server/Network/ClientMessage.cs
+++ b/Source/ACE.Server/Network/ClientMessage.cs
@@ -4,12 +4,13 @@ namespace ACE.Server.Network
{
public class ClientMessage
{
- public BinaryReader Payload { get; }
-
public MemoryStream Data { get; }
+ public BinaryReader Payload { get; }
+
public uint Opcode { get; }
+ /// stream must be at least 4 bytes in length remaining to read
public ClientMessage(MemoryStream stream)
{
Data = stream;
@@ -17,6 +18,7 @@ public ClientMessage(MemoryStream stream)
Opcode = Payload.ReadUInt32();
}
+ /// data must be at least 4 bytes in length
public ClientMessage(byte[] data)
{
Data = new MemoryStream(data);
diff --git a/Source/ACE.Server/Network/MessageBuffer.cs b/Source/ACE.Server/Network/MessageBuffer.cs
index 1ba5d7be4f..4d12b52fad 100644
--- a/Source/ACE.Server/Network/MessageBuffer.cs
+++ b/Source/ACE.Server/Network/MessageBuffer.cs
@@ -30,16 +30,25 @@ public void AddFragment(ClientPacketFragment fragment)
}
}
- public ClientMessage GetMessage()
+ ///
+ /// This will return null if not enough data exists to create a valid ClientMessage (4 bytes minimum are required)
+ ///
+ public ClientMessage TryGetMessage()
{
fragments.Sort(delegate (ClientPacketFragment x, ClientPacketFragment y) { return x.Header.Index - y.Header.Index; });
+
MemoryStream stream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(stream);
foreach (ClientPacketFragment fragment in fragments)
{
writer.Write(fragment.Data);
}
+
stream.Seek(0, SeekOrigin.Begin);
+
+ if (stream.Length < 4) // ClientMessage must be a minimum of 4 bytes in length
+ return null;
+
return new ClientMessage(stream);
}
}
diff --git a/Source/ACE.Server/Network/NetworkSession.cs b/Source/ACE.Server/Network/NetworkSession.cs
index dc3a811e70..f7119bf1fe 100644
--- a/Source/ACE.Server/Network/NetworkSession.cs
+++ b/Source/ACE.Server/Network/NetworkSession.cs
@@ -475,7 +475,7 @@ private void ProcessFragment(ClientPacketFragment fragment)
{
// The buffer is complete, so we can go ahead and handle
packetLog.DebugFormat("[{0}] Buffer {1} is complete", session.LoggingIdentifier, buffer.Sequence);
- message = buffer.GetMessage();
+ message = buffer.TryGetMessage();
MessageBuffer removed = null;
partialFragments.TryRemove(fragment.Header.Sequence, out removed);
}
@@ -495,7 +495,9 @@ private void ProcessFragment(ClientPacketFragment fragment)
{
// Packet is not split, proceed with handling it.
packetLog.DebugFormat("[{0}] Fragment {1} is not split", session.LoggingIdentifier, fragment.Header.Sequence);
- message = new ClientMessage(fragment.Data);
+
+ if (fragment.Data.Length >= 4) // ClientMessage must be a minimum of 4 bytes in length
+ message = new ClientMessage(fragment.Data);
}
// If message is not null, we have a complete message to handle