From cd6fc87eb4b29fbbee420f0ae994dea7111a84a4 Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Thu, 1 Mar 2018 19:30:27 +0200 Subject: [PATCH] Fixed object header issues and "trying to read past the buffer size" errors caused by NetEntityEvents for removed entities. EntityEventManager sends an empty event with an ID of 0 if the entity doesn't exist anymore when writing the event. The recipient should simply skip over these messages and read the next one, but clients only did so if the event is the next unreceived one, causing the rest of the messages to be read incorrectly (which could lead to various sorts of problems in addition to the header and buffer size errors). The server didn't deal with the empty events correctly either, it increased the last received ID even if the received event was not the one the server is waiting for, potentially causing other non-empty events to be ignored. + Added an error message if the size of an NetEntityEvent is larger than 255 bytes. Not only is that excessively large for an event, but the length of the event is written as a byte and larger ones may again cause messages to be read incorrectly. Most events should be nowhere near 255 bytes, but now that the descriptions and tags of a spawned item are included in the item spawn messages there's the possibility that some events are too large. --- .../NetEntityEvent/ClientEntityEventManager.cs | 10 +++++----- .../Networking/NetEntityEvent/NetEntityEventManager.cs | 7 ++++++- .../NetEntityEvent/ServerEntityEventManager.cs | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Barotrauma/BarotraumaClient/Source/Networking/NetEntityEvent/ClientEntityEventManager.cs b/Barotrauma/BarotraumaClient/Source/Networking/NetEntityEvent/ClientEntityEventManager.cs index a66c0bf2b..2ea912a2f 100644 --- a/Barotrauma/BarotraumaClient/Source/Networking/NetEntityEvent/ClientEntityEventManager.cs +++ b/Barotrauma/BarotraumaClient/Source/Networking/NetEntityEvent/ClientEntityEventManager.cs @@ -132,21 +132,21 @@ namespace Barotrauma.Networking UInt16 firstEventID = msg.ReadUInt16(); int eventCount = msg.ReadByte(); - + for (int i = 0; i < eventCount; i++) { - UInt16 thisEventID = (UInt16)(firstEventID + (UInt16)i); + UInt16 thisEventID = (UInt16)(firstEventID + (UInt16)i); UInt16 entityID = msg.ReadUInt16(); - if (entityID == 0 && thisEventID == (UInt16)(lastReceivedID + 1)) + if (entityID == 0) { msg.ReadPadBits(); - lastReceivedID++; + if (thisEventID == (UInt16)(lastReceivedID + 1)) lastReceivedID++; continue; } byte msgLength = msg.ReadByte(); - + IServerSerializable entity = Entity.FindEntityByID(entityID) as IServerSerializable; entities.Add(entity); diff --git a/Barotrauma/BarotraumaShared/Source/Networking/NetEntityEvent/NetEntityEventManager.cs b/Barotrauma/BarotraumaShared/Source/Networking/NetEntityEvent/NetEntityEventManager.cs index 93d25b13a..fad368b6e 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/NetEntityEvent/NetEntityEventManager.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/NetEntityEvent/NetEntityEventManager.cs @@ -45,7 +45,12 @@ namespace Barotrauma.Networking //no more room in this packet break; } - + + if (tempEventBuffer.LengthBytes > 255) + { + DebugConsole.ThrowError("Too much data in network event for entity \"" + e.Entity.ToString() + "\" (" + tempEventBuffer.LengthBytes + " bytes"); + } + //the ID has been taken by another entity (the original entity has been removed) -> write an empty event if (Entity.FindEntityByID(e.Entity.ID) != e.Entity) { diff --git a/Barotrauma/BarotraumaShared/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs b/Barotrauma/BarotraumaShared/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs index 7dad4627d..5c0986cd4 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs @@ -326,7 +326,7 @@ namespace Barotrauma.Networking if (entityID == 0) { msg.ReadPadBits(); - sender.LastSentEntityEventID++; + if (thisEventID == (UInt16)(sender.LastSentEntityEventID + 1)) sender.LastSentEntityEventID++; continue; }