Prevent buffer overflows when using streams

This commit is contained in:
Chris Cowan 2025-06-27 19:27:22 -07:00 committed by Ricardo Luís Vaz Silva
commit ab7b1642bc
18 changed files with 600 additions and 388 deletions

View file

@ -40,6 +40,7 @@
#include "c_console.h"
#include "c_dispatch.h"
#include "c_cvars.h"
#include "d_protocol.h"
#include "engineerrors.h"
#include "printf.h"
#include "palutil.h"
@ -1265,12 +1266,10 @@ void FilterCompactCVars (TArray<FBaseCVar *> &cvars, uint32_t filter)
}
}
void C_WriteCVars (uint8_t **demo_p, uint32_t filter, bool compact)
void C_WriteCVars (TArrayView<uint8_t>& demo_p, uint32_t filter, bool compact)
{
FString dump = C_GetMassCVarString(filter, compact);
size_t dumplen = dump.Len() + 1; // include terminating \0
memcpy(*demo_p, dump.GetChars(), dumplen);
*demo_p += dumplen;
WriteFString(dump, demo_p);
}
FString C_GetMassCVarString (uint32_t filter, bool compact)
@ -1306,9 +1305,9 @@ FString C_GetMassCVarString (uint32_t filter, bool compact)
return dump;
}
void C_ReadCVars (uint8_t **demo_p)
void C_ReadCVars (TArrayView<uint8_t>& demo_p)
{
char *ptr = *((char **)demo_p);
char *ptr = (char *)demo_p.Data();
char *breakpt;
if (*ptr++ != '\\')
@ -1371,7 +1370,7 @@ void C_ReadCVars (uint8_t **demo_p)
}
}
}
*demo_p += strlen (*((char **)demo_p)) + 1;
AdvanceStream(demo_p, strlen((char*)demo_p.Data()) + 1);
}
struct FCVarBackup

View file

@ -269,7 +269,7 @@ private:
// These need to go away!
friend FString C_GetMassCVarString (uint32_t filter, bool compact);
friend void C_SerializeCVars(FSerializer& arc, const char* label, uint32_t filter);
friend void C_ReadCVars (uint8_t **demo_p);
friend void C_ReadCVars (TArrayView<uint8_t>& demo_p);
friend void C_BackupCVars (void);
friend FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev);
friend FBaseCVar *FindCVarSub (const char *var_name, int namelen);
@ -288,12 +288,12 @@ private:
// the cvar names are omitted to save space.
FString C_GetMassCVarString (uint32_t filter, bool compact=false);
// Writes all cvars that could effect demo sync to *demo_p. These are
// Writes all cvars that could effect demo sync to demo_p. These are
// cvars that have either CVAR_SERVERINFO or CVAR_DEMOSAVE set.
void C_WriteCVars (uint8_t **demo_p, uint32_t filter, bool compact=false);
void C_WriteCVars (TArrayView<uint8_t>& demo_p, uint32_t filter, bool compact=false);
// Read all cvars from *demo_p and set them appropriately.
void C_ReadCVars (uint8_t **demo_p);
// Read all cvars from demo_p and set them appropriately.
void C_ReadCVars (TArrayView<uint8_t>& demo_p);
void C_InstallHandlers(ConsoleCallbacks* cb);

View file

@ -191,10 +191,10 @@ size_t Net_SetEngineInfo(uint8_t*& stream);
bool Net_VerifyEngine(uint8_t*& stream);
void Net_SetupUserInfo();
const char* Net_GetClientName(int client, unsigned int charLimit);
size_t Net_SetUserInfo(int client, uint8_t*& stream);
size_t Net_ReadUserInfo(int client, uint8_t*& stream);
size_t Net_ReadGameInfo(uint8_t*& stream);
size_t Net_SetGameInfo(uint8_t*& stream);
void Net_SetUserInfo(int client, TArrayView<uint8_t>& stream);
void Net_ReadUserInfo(int client, TArrayView<uint8_t>& stream);
void Net_ReadGameInfo(TArrayView<uint8_t>& stream);
void Net_SetGameInfo(TArrayView<uint8_t>& stream);
static SOCKET CreateUDPSocket()
{
@ -833,7 +833,7 @@ static bool Host_CheckForConnections(void* connected)
{
if (Connected[RemoteClient].Status == CSTAT_CONNECTING)
{
uint8_t* stream = &NetBuffer[2];
TArrayView<uint8_t> stream = TArrayView(&NetBuffer[2], MAX_MSGLEN-2);
Net_ReadUserInfo(RemoteClient, stream);
Connected[RemoteClient].Status = CSTAT_WAITING;
I_NetClientConnected(RemoteClient, 16u);
@ -886,8 +886,9 @@ static bool Host_CheckForConnections(void* connected)
memcpy(&NetBuffer[3], GameID, 8);
NetBufferLength = 11u;
uint8_t* stream = &NetBuffer[NetBufferLength];
NetBufferLength += Net_SetGameInfo(stream);
TArrayView<uint8_t> stream = TArrayView(&NetBuffer[NetBufferLength], MAX_MSGLEN - NetBufferLength);
Net_SetGameInfo(stream);
NetBufferLength += stream.Data() - &NetBuffer[NetBufferLength];
SendPacket(con.Address);
clientReady = false;
}
@ -911,8 +912,9 @@ static bool Host_CheckForConnections(void* connected)
NetBufferLength += addrSize;
}
uint8_t* stream = &NetBuffer[NetBufferLength];
NetBufferLength += Net_SetUserInfo(i, stream);
TArrayView<uint8_t> stream = TArrayView(&NetBuffer[NetBufferLength], MAX_MSGLEN - NetBufferLength);
Net_SetUserInfo(i, stream);
NetBufferLength += stream.Data() - &NetBuffer[NetBufferLength];
SendPacket(con.Address);
}
clientReady = false;
@ -1131,7 +1133,7 @@ static bool Guest_ContactHost(void* unused)
{
TicDup = clamp<int>(NetBuffer[2], 1, MAXTICDUP);
memcpy(GameID, &NetBuffer[3], 8);
uint8_t* stream = &NetBuffer[11];
TArrayView<uint8_t> stream = TArrayView(&NetBuffer[11], MAX_MSGLEN - 11);
Net_ReadGameInfo(stream);
Connected[consoleplayer].bHasGameInfo = true;
}
@ -1158,7 +1160,7 @@ static bool Guest_ContactHost(void* unused)
{
Connected[c].Status = CSTAT_READY;
}
uint8_t* stream = &NetBuffer[byte];
TArrayView<uint8_t> stream = TArrayView(&NetBuffer[byte], MAX_MSGLEN - byte);
Net_ReadUserInfo(c, stream);
SetClientAck(consoleplayer, c, true);
@ -1199,8 +1201,9 @@ static bool Guest_ContactHost(void* unused)
NetBuffer[1] = PRE_USER_INFO;
NetBufferLength = 2u;
uint8_t* stream = &NetBuffer[NetBufferLength];
NetBufferLength += Net_SetUserInfo(consoleplayer, stream);
TArrayView<uint8_t> stream = TArrayView(&NetBuffer[NetBufferLength], MAX_MSGLEN - NetBufferLength);
Net_SetUserInfo(consoleplayer, stream);
NetBufferLength += stream.Data() - &NetBuffer[NetBufferLength];
SendPacket(Connected[0].Address);
}
else if (con.Status == CSTAT_WAITING)

View file

@ -265,6 +265,11 @@ FString &FString::operator = (const char *copyStr)
return *this;
}
TArrayView<uint8_t> FString::GetTArrayView()
{
return TArrayView((uint8_t*)Chars, Len() + 1);
}
void FString::Format (const char *fmt, ...)
{
va_list arglist;

View file

@ -166,6 +166,8 @@ public:
const char *GetChars() const { return Chars; }
TArrayView<uint8_t> GetTArrayView();
const char &operator[] (int index) const { return Chars[index]; }
#if defined(_WIN32) && !defined(_WIN64) && defined(_MSC_VER)
// Compiling 32-bit Windows source with MSVC: size_t is typedefed to an