mirror of
https://github.com/ddnet/ddnet.git
synced 2024-10-18 14:58:19 +00:00
Fix snapshot builder creating too large snapshots
The snapshot builder was only considering the size of the data and of the new item being created in the `NewItem` function but not the size of the `CSnapshot` class and the size of the offsets (one `int` for each item including the new one). This could lead to snapshots being too large, which could cause the server to crash when the snapshots were copied into buffers of size `CSnapshot::MAX_SIZE`. However, it should be unlikely for this to happen normally, as the maximum number of snap items (`CSnapshot::MAX_ITEMS`, which is `1024`) is usually reached before the maximum snapshot size. Also check in the `CSnapshot::IsValid` function that the snapshot is not too large (`CSnapshot::MAX_SIZE`) and check that the number of items is not too large (`CSnapshot::MAX_ITEMS`).
This commit is contained in:
parent
a8424150a4
commit
67068ade90
|
@ -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();
|
||||||
|
@ -744,12 +751,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
|
||||||
|
@ -794,11 +804,15 @@ 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)
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
dbg_assert(m_DataSize < CSnapshot::MAX_SIZE, "too much data");
|
|
||||||
dbg_assert(m_NumItems < CSnapshot::MAX_ITEMS, "too many items");
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -824,11 +838,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();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue