Merge pull request #8995 from Robyt3/Snapshot-Builder-Size-Fix

Fix snapshot builder creating too large snapshots, do not add snap item if extended item type could not be added, fix snapshot handling when converting 0.7 demo snapshot fails
This commit is contained in:
Dennis Felsing 2024-09-19 14:49:21 +00:00 committed by GitHub
commit 6086a93bd6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 62 additions and 41 deletions

View file

@ -2006,10 +2006,11 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
if(DemoSnapSize < 0)
{
dbg_msg("sixup", "demo snapshot failed. error=%d", DemoSnapSize);
return;
}
}
if(DemoSnapSize >= 0)
{
// add snapshot to demo
for(auto &DemoRecorder : m_aDemoRecorder)
{
@ -2020,6 +2021,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
}
}
}
}
// apply snapshot, cycle pointers
m_aReceivedSnapshots[Conn]++;

View file

@ -8,17 +8,6 @@ void CSnapshotBuilder::Init7(const CSnapshot *pSnapshot)
// but the snap we are building is a 0.6 snap
m_Sixup = false;
if(pSnapshot->m_DataSize + sizeof(CSnapshot) + pSnapshot->m_NumItems * sizeof(int) * 2 > CSnapshot::MAX_SIZE || pSnapshot->m_NumItems > CSnapshot::MAX_ITEMS)
{
// key and offset per item
dbg_assert(m_DataSize + sizeof(CSnapshot) + m_NumItems * sizeof(int) * 2 < CSnapshot::MAX_SIZE, "too much data");
dbg_assert(m_NumItems < CSnapshot::MAX_ITEMS, "too many items");
dbg_msg("sixup", "demo recording failed on invalid snapshot");
m_DataSize = 0;
m_NumItems = 0;
return;
}
m_DataSize = pSnapshot->m_DataSize;
m_NumItems = pSnapshot->m_NumItems;
mem_copy(m_aOffsets, pSnapshot->Offsets(), sizeof(int) * m_NumItems);

View file

@ -135,8 +135,15 @@ void CSnapshot::DebugDump() const
bool CSnapshot::IsValid(size_t ActualSize) const
{
// validate total size
if(ActualSize < sizeof(CSnapshot) || m_NumItems < 0 || m_DataSize < 0 || ActualSize != TotalSize())
if(ActualSize < sizeof(CSnapshot) ||
ActualSize > MAX_SIZE ||
m_NumItems < 0 ||
m_NumItems > MAX_ITEMS ||
m_DataSize < 0 ||
ActualSize != TotalSize())
{
return false;
}
// validate item offsets
const int *pOffsets = Offsets();
@ -735,8 +742,11 @@ int *CSnapshotBuilder::GetItemData(int Key)
{
for(int i = 0; i < m_NumItems; i++)
{
if(GetItem(i)->Key() == Key)
return GetItem(i)->Data();
CSnapshotItem *pItem = GetItem(i);
if(pItem->Key() == Key)
{
return pItem->Data();
}
}
return nullptr;
}
@ -744,12 +754,15 @@ int *CSnapshotBuilder::GetItemData(int Key)
int CSnapshotBuilder::Finish(void *pSnapData)
{
// flatten and make the snapshot
dbg_assert(m_NumItems <= CSnapshot::MAX_ITEMS, "Too many snap items");
CSnapshot *pSnap = (CSnapshot *)pSnapData;
pSnap->m_DataSize = m_DataSize;
pSnap->m_NumItems = m_NumItems;
const size_t TotalSize = pSnap->TotalSize();
dbg_assert(TotalSize <= (size_t)CSnapshot::MAX_SIZE, "Snapshot too large");
mem_copy(pSnap->Offsets(), m_aOffsets, pSnap->OffsetSize());
mem_copy(pSnap->DataStart(), m_aData, m_DataSize);
return pSnap->TotalSize();
return TotalSize;
}
int CSnapshotBuilder::GetTypeFromIndex(int Index) const
@ -757,17 +770,22 @@ int CSnapshotBuilder::GetTypeFromIndex(int Index) const
return CSnapshot::MAX_TYPE - Index;
}
void CSnapshotBuilder::AddExtendedItemType(int Index)
bool CSnapshotBuilder::AddExtendedItemType(int Index)
{
dbg_assert(0 <= Index && Index < m_NumExtendedItemTypes, "index out of range");
int TypeId = m_aExtendedItemTypes[Index];
CUuid Uuid = g_UuidManager.GetUuid(TypeId);
int *pUuidItem = (int *)NewItem(0, GetTypeFromIndex(Index), sizeof(Uuid)); // NETOBJTYPE_EX
if(pUuidItem)
int *pUuidItem = static_cast<int *>(NewItem(0, GetTypeFromIndex(Index), sizeof(CUuid))); // NETOBJTYPE_EX
if(pUuidItem == nullptr)
{
return false;
}
const int TypeId = m_aExtendedItemTypes[Index];
const CUuid Uuid = g_UuidManager.GetUuid(TypeId);
for(size_t i = 0; i < sizeof(CUuid) / sizeof(int32_t); i++)
{
pUuidItem[i] = bytes_be_to_uint(&Uuid.m_aData[i * sizeof(int32_t)]);
}
return true;
}
int CSnapshotBuilder::GetExtendedItemTypeIndex(int TypeId)
@ -783,9 +801,13 @@ int CSnapshotBuilder::GetExtendedItemTypeIndex(int TypeId)
int Index = m_NumExtendedItemTypes;
m_NumExtendedItemTypes++;
m_aExtendedItemTypes[Index] = TypeId;
AddExtendedItemType(Index);
if(AddExtendedItemType(Index))
{
return Index;
}
m_NumExtendedItemTypes--;
return -1;
}
void *CSnapshotBuilder::NewItem(int Type, int Id, int Size)
{
@ -794,19 +816,27 @@ void *CSnapshotBuilder::NewItem(int Type, int Id, int Size)
return nullptr;
}
if(m_DataSize + sizeof(CSnapshotItem) + Size >= CSnapshot::MAX_SIZE ||
m_NumItems + 1 >= CSnapshot::MAX_ITEMS)
if(m_NumItems >= CSnapshot::MAX_ITEMS)
{
dbg_assert(m_DataSize < CSnapshot::MAX_SIZE, "too much data");
dbg_assert(m_NumItems < CSnapshot::MAX_ITEMS, "too many items");
return nullptr;
}
bool Extended = false;
if(Type >= OFFSET_UUID)
const size_t OffsetSize = (m_NumItems + 1) * sizeof(int);
const size_t ItemSize = sizeof(CSnapshotItem) + Size;
if(sizeof(CSnapshot) + OffsetSize + m_DataSize + ItemSize > CSnapshot::MAX_SIZE)
{
Extended = true;
Type = GetTypeFromIndex(GetExtendedItemTypeIndex(Type));
return nullptr;
}
const bool Extended = Type >= OFFSET_UUID;
if(Extended)
{
const int ExtendedItemTypeIndex = GetExtendedItemTypeIndex(Type);
if(ExtendedItemTypeIndex == -1)
{
return nullptr;
}
Type = GetTypeFromIndex(ExtendedItemTypeIndex);
}
CSnapshotItem *pObj = (CSnapshotItem *)(m_aData + m_DataSize);
@ -824,11 +854,11 @@ void *CSnapshotBuilder::NewItem(int Type, int Id, int Size)
else if(Type < 0)
return nullptr;
mem_zero(pObj, sizeof(CSnapshotItem) + Size);
pObj->m_TypeAndId = (Type << 16) | Id;
m_aOffsets[m_NumItems] = m_DataSize;
m_DataSize += sizeof(CSnapshotItem) + Size;
m_DataSize += ItemSize;
m_NumItems++;
mem_zero(pObj->Data(), Size);
return pObj->Data();
}

View file

@ -158,7 +158,7 @@ class CSnapshotBuilder
int m_aExtendedItemTypes[MAX_EXTENDED_ITEM_TYPES];
int m_NumExtendedItemTypes;
void AddExtendedItemType(int Index);
bool AddExtendedItemType(int Index);
int GetExtendedItemTypeIndex(int TypeId);
int GetTypeFromIndex(int Index) const;