Fix memory leaks and add bounds checks in packet/drop handling

GetNewDrop() allocated newdrop up front but returned NULL without
freeing it on every rejection path (failed drop-rate check, missing
drop table, unknown item type, etc.), leaking on every non-drop roll.
Free it on all early-return paths, and only assign a clientid once a
drop is actually going to be returned.

CPacket::AddByte/Word/DWord/QWord/Float now bounds-check against the
buffer before writing, preventing an overflow if a packet is built
past its allocated size.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
ThomasandClaude Sonnet 5 committed 2026-07-09 06:35:18 +02:00
1 parent f59158a95c
commit 5f600d0e61
2 files changed
+16 -5

No files matched your search

+10 -4
View File
@@ -133,10 +133,9 @@ CDrop* CWorldServer::GetNewDrop( CMonster* thismon )
CMDrops* thisdrop = NULL;
CMDrops* testdrop = NULL;
newdrop->clientid = GetNewClientID( );
newdrop->posMap = thismon->Position->Map;
newdrop->pos = RandInCircle( thismon->Position->current, 3 );
//newdrop->droptime = time(NULL);
newdrop->droptime = time(NULL);
newdrop->owner = thismon->MonsterDrop->firsthit;
newdrop->thisparty = thismon->thisparty;
ClearItem(newdrop->item);
@@ -158,6 +157,7 @@ CDrop* CWorldServer::GetNewDrop( CMonster* thismon )
{
if( thisclient->Session->codedebug )
SendPM(thisclient, "Drop rate check failed with %i. No drop this time",droprand);
delete newdrop;
return NULL; // no drop here. not this time anyway.
}
@@ -177,6 +177,7 @@ CDrop* CWorldServer::GetNewDrop( CMonster* thismon )
{
SendPM(thisclient, "Zuly drop selected " );
}
newdrop->clientid = GetNewClientID( );
return newdrop;
}
//now check for item drops
@@ -194,7 +195,7 @@ CDrop* CWorldServer::GetNewDrop( CMonster* thismon )
for(i=0;i<GServer->MDropList.size();i++)
{
testdrop = GServer->MDropList.at(i);
if(testdrop == NULL) return NULL;
if(testdrop == NULL) { delete newdrop; return NULL; }
if(testdrop->Dropid == thismon->Position->Map)
{
thisdrop = testdrop;
@@ -211,7 +212,7 @@ CDrop* CWorldServer::GetNewDrop( CMonster* thismon )
for(i=0;i<GServer->MDropList.size();i++)
{
testdrop = GServer->MDropList.at(i);
if(testdrop == NULL) return NULL;
if(testdrop == NULL) { delete newdrop; return NULL; }
if(testdrop->Dropid == thismon->thisnpc->dropid)
{
thisdrop = testdrop;
@@ -225,6 +226,7 @@ CDrop* CWorldServer::GetNewDrop( CMonster* thismon )
if(thisdrop == NULL)
{
Log(MSG_WARNING, "Thisdrop is NULL [getdrop]" );
delete newdrop;
return NULL;
}
newdrop->type = 2; //Item
@@ -250,6 +252,7 @@ CDrop* CWorldServer::GetNewDrop( CMonster* thismon )
if(thisdrop->item[itemindex] == 0)
{
Log(MSG_DEBUG, "item at itemindex %i does not exist",itemindex );
delete newdrop;
return NULL; //no item listed for this dropid
}
//ok we found an item. Now we process it.
@@ -296,6 +299,7 @@ CDrop* CWorldServer::GetNewDrop( CMonster* thismon )
break;
default:
Log(MSG_DEBUG, "itemtype %i does not exist",newdrop->item.itemtype );
delete newdrop;
return NULL;
break;
}
@@ -399,9 +403,11 @@ CDrop* CWorldServer::GetNewDrop( CMonster* thismon )
{
SendPM(thisclient, "Dropped item type: %i ID: %i count %i", newdrop->item.itemtype, newdrop->item.itemnum,newdrop->item.count);
}
newdrop->clientid = GetNewClientID( );
return newdrop;
}
delete newdrop;
return NULL;
// did not qualify to drop anything this time
}