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,17 +2006,19 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
if(DemoSnapSize < 0) if(DemoSnapSize < 0)
{ {
dbg_msg("sixup", "demo snapshot failed. error=%d", DemoSnapSize); dbg_msg("sixup", "demo snapshot failed. error=%d", DemoSnapSize);
return;
} }
} }
// add snapshot to demo if(DemoSnapSize >= 0)
for(auto &DemoRecorder : m_aDemoRecorder)
{ {
if(DemoRecorder.IsRecording()) // add snapshot to demo
for(auto &DemoRecorder : m_aDemoRecorder)
{ {
// write snapshot if(DemoRecorder.IsRecording())
DemoRecorder.RecordSnapshot(GameTick, IsSixup() ? pSnapSeven : pTmpBuffer3, DemoSnapSize); {
// write snapshot
DemoRecorder.RecordSnapshot(GameTick, IsSixup() ? pSnapSeven : pTmpBuffer3, DemoSnapSize);
}
} }
} }
} }

View file

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

View file

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