From 42bca87c9af79984b8bf13907c630945f6f1cd01 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 11 Feb 2024 05:33:20 -0800 Subject: [PATCH 1/6] Got_Luacmd: ensure lua stack is large enough for command arguments --- src/lua_consolelib.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 8a205fb51..98591bec9 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -30,6 +30,12 @@ return luaL_error(L, "HUD rendering code should not call this function!"); static consvar_t *this_cvar; +static void clear_lua_stack(void) +{ + if (gL) // check if Lua is actually turned on first, you dummmy -- Monster Iestyn 04/07/18 + lua_settop(gL, 0); // clear stack +} + void Got_Luacmd(UINT8 **cp, INT32 playernum) { UINT8 i, argc, flags; @@ -74,6 +80,13 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum) lua_remove(gL, -2); // pop command info table + if (!lua_checkstack(gL, argc)) // player + command arguments + { + clear_lua_stack(); + CONS_Alert(CONS_WARNING, "lua command stack overflow from %s (%d, need %d more)\n", player_names[playernum], lua_gettop(gL), argc); + return; + } + LUA_PushUserdata(gL, &players[playernum], META_PLAYER); for (i = 1; i < argc; i++) { @@ -85,8 +98,7 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum) deny: //must be hacked/buggy client - if (gL) // check if Lua is actually turned on first, you dummmy -- Monster Iestyn 04/07/18 - lua_settop(gL, 0); // clear stack + clear_lua_stack(); CONS_Alert(CONS_WARNING, M_GetText("Illegal lua command received from %s\n"), player_names[playernum]); if (server) From 6d64d15216cf8e84f7f6c9fed088afabc64297f6 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 11 Feb 2024 05:35:42 -0800 Subject: [PATCH 2/6] Got_Saycmd: copy message content into intermediate buffer This prevents modifying the original buffer at the cleanup step as well as potentially writing out of bounds. --- src/hu_stuff.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 39ccfbb21..74a2a8ff0 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -665,6 +665,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) SINT8 target; UINT8 flags; const char *dispname; + char buf[HU_MAXMSGLEN + 1]; char *msg; boolean action = false; char *ptr; @@ -678,8 +679,8 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) target = READSINT8(*p); flags = READUINT8(*p); playernum = READUINT8(*p); - msg = (char *)*p; - SKIPSTRINGL(*p, HU_MAXMSGLEN + 1); + msg = buf; + READSTRINGL(*p, msg, HU_MAXMSGLEN + 1); //check for invalid characters (0x80 or above) { From c0b823fe6a1e4715a59ca098d4b54c267849453a Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 11 Feb 2024 05:39:18 -0800 Subject: [PATCH 3/6] Let READ macros be used with const pointers --- src/byteptr.h | 54 +++++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/byteptr.h b/src/byteptr.h index 5416a8455..00bf34c36 100644 --- a/src/byteptr.h +++ b/src/byteptr.h @@ -52,25 +52,25 @@ extern "C" { // what is this? #if defined (__GNUC__) && defined (DEALIGNED) -#define READUINT8(p) ({ UINT8 *p_tmp = (UINT8 *)p; UINT8 b; memcpy(&b, p, sizeof( UINT8)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) -#define READSINT8(p) ({ SINT8 *p_tmp = (SINT8 *)p; SINT8 b; memcpy(&b, p, sizeof( SINT8)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) -#define READINT16(p) ({ INT16 *p_tmp = (INT16 *)p; INT16 b; memcpy(&b, p, sizeof( INT16)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) -#define READUINT16(p) ({ UINT16 *p_tmp = (UINT16 *)p; UINT16 b; memcpy(&b, p, sizeof( UINT16)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) -#define READINT32(p) ({ INT32 *p_tmp = (INT32 *)p; INT32 b; memcpy(&b, p, sizeof( INT32)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) -#define READUINT32(p) ({ UINT32 *p_tmp = (UINT32 *)p; UINT32 b; memcpy(&b, p, sizeof( UINT32)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) -#define READCHAR(p) ({ char *p_tmp = (char *)p; char b; memcpy(&b, p, sizeof( char)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) -#define READFIXED(p) ({ fixed_t *p_tmp = (fixed_t *)p; fixed_t b; memcpy(&b, p, sizeof(fixed_t)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) -#define READANGLE(p) ({ angle_t *p_tmp = (angle_t *)p; angle_t b; memcpy(&b, p, sizeof(angle_t)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) +#define READUINT8(p) ({ const UINT8 *p_tmp = (const UINT8 *)p; UINT8 b; memcpy(&b, p, sizeof( UINT8)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; }) +#define READSINT8(p) ({ const SINT8 *p_tmp = (const SINT8 *)p; SINT8 b; memcpy(&b, p, sizeof( SINT8)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; }) +#define READINT16(p) ({ const INT16 *p_tmp = (const INT16 *)p; INT16 b; memcpy(&b, p, sizeof( INT16)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; }) +#define READUINT16(p) ({ const UINT16 *p_tmp = (const UINT16 *)p; UINT16 b; memcpy(&b, p, sizeof( UINT16)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; }) +#define READINT32(p) ({ const INT32 *p_tmp = (const INT32 *)p; INT32 b; memcpy(&b, p, sizeof( INT32)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; }) +#define READUINT32(p) ({ const UINT32 *p_tmp = (const UINT32 *)p; UINT32 b; memcpy(&b, p, sizeof( UINT32)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; }) +#define READCHAR(p) ({ const char *p_tmp = (const char *)p; char b; memcpy(&b, p, sizeof( char)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; }) +#define READFIXED(p) ({ const fixed_t *p_tmp = (const fixed_t *)p; fixed_t b; memcpy(&b, p, sizeof(fixed_t)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; }) +#define READANGLE(p) ({ const angle_t *p_tmp = (const angle_t *)p; angle_t b; memcpy(&b, p, sizeof(angle_t)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; }) #else -#define READUINT8(p) ((UINT8*)(*(void**)(&(p)) = (void*)&((UINT8*)(p))[1]))[-1] -#define READSINT8(p) ((SINT8*)(*(void**)(&(p)) = (void*)&((SINT8*)(p))[1]))[-1] -#define READINT16(p) ((INT16*)(*(void**)(&(p)) = (void*)&((INT16*)(p))[1]))[-1] -#define READUINT16(p) ((UINT16*)(*(void**)(&(p)) = (void*)&((UINT16*)(p))[1]))[-1] -#define READINT32(p) ((INT32*)(*(void**)(&(p)) = (void*)&((INT32*)(p))[1]))[-1] -#define READUINT32(p) ((UINT32*)(*(void**)(&(p)) = (void*)&((UINT32*)(p))[1]))[-1] -#define READCHAR(p) ((char*)(*(void**)(&(p)) = (void*)&((char*)(p))[1]))[-1] -#define READFIXED(p) ((fixed_t*)(*(void**)(&(p)) = (void*)&((fixed_t*)(p))[1]))[-1] -#define READANGLE(p) ((angle_t*)(*(void**)(&(p)) = (void*)&((angle_t*)(p))[1]))[-1] +#define READUINT8(p) ((const UINT8*)(*(const void**)(&(p)) = (const void*)&((const UINT8*)(p))[1]))[-1] +#define READSINT8(p) ((const SINT8*)(*(const void**)(&(p)) = (const void*)&((const SINT8*)(p))[1]))[-1] +#define READINT16(p) ((const INT16*)(*(const void**)(&(p)) = (const void*)&((const INT16*)(p))[1]))[-1] +#define READUINT16(p) ((const UINT16*)(*(const void**)(&(p)) = (const void*)&((const UINT16*)(p))[1]))[-1] +#define READINT32(p) ((const INT32*)(*(const void**)(&(p)) = (const void*)&((const INT32*)(p))[1]))[-1] +#define READUINT32(p) ((const UINT32*)(*(const void**)(&(p)) = (const void*)&((const UINT32*)(p))[1]))[-1] +#define READCHAR(p) ((const char*)(*(const void**)(&(p)) = (const void*)&((const char*)(p))[1]))[-1] +#define READFIXED(p) ((const fixed_t*)(*(const void**)(&(p)) = (const void*)&((const fixed_t*)(p))[1]))[-1] +#define READANGLE(p) ((const angle_t*)(*(const void**)(&(p)) = (const void*)&((const angle_t*)(p))[1]))[-1] #endif #else //SRB2_BIG_ENDIAN @@ -133,15 +133,15 @@ FUNCINLINE static ATTRINLINE UINT32 readulong(void *ptr) return (ucp[3] << 24) | (ucp[2] << 16) | (ucp[1] << 8) | ucp[0]; } -#define READUINT8(p) ((UINT8*)(p = (void*)&((UINT8*)p)[1]))[-1] -#define READSINT8(p) ((SINT8*)(p = (void*)&((SINT8*)p)[1]))[-1] -#define READINT16(p) readshort(&((INT16*)(p = (void*)&((INT16*)p)[1]))[-1]) -#define READUINT16(p) readushort(&((UINT16*)(p = (void*)&((UINT16*)p)[1]))[-1]) -#define READINT32(p) readlong(&((INT32*)(p = (void*)&((INT32*)p)[1]))[-1]) -#define READUINT32(p) readulong(&((UINT32*)(p = (void*)&((UINT32*)p)[1])) -#define READCHAR(p) ((char*)(p = (void*)&((char*)p)[1]))[-1] -#define READFIXED(p) readlong(&((fixed_t*)(p = (void*)&((fixed_t*)p)[1]))[-1]) -#define READANGLE(p) readulong(&((angle_t*)(p = (void*)&((angle_t*)p)[1]))[-1]) +#define READUINT8(p) ((const UINT8*)(p = (const void*)&((const UINT8*)p)[1]))[-1] +#define READSINT8(p) ((const SINT8*)(p = (const void*)&((const SINT8*)p)[1]))[-1] +#define READINT16(p) readshort(&((const INT16*)(p = (const void*)&((const INT16*)p)[1]))[-1]) +#define READUINT16(p) readushort(&((const UINT16*)(p = (const void*)&((const UINT16*)p)[1]))[-1]) +#define READINT32(p) readlong(&((const INT32*)(p = (const void*)&((const INT32*)p)[1]))[-1]) +#define READUINT32(p) readulong(&((const UINT32*)(p = (const void*)&((const UINT32*)p)[1])) +#define READCHAR(p) ((const char*)(p = (const void*)&((const char*)p)[1]))[-1] +#define READFIXED(p) readlong(&((const fixed_t*)(p = (const void*)&((const fixed_t*)p)[1]))[-1]) +#define READANGLE(p) readulong(&((const angle_t*)(p = (const void*)&((const angle_t*)p)[1]))[-1]) #endif //SRB2_BIG_ENDIAN #undef DEALIGNED From 4ee00d433328391f1333d9be3a7b1fc8c87e1e4f Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 11 Feb 2024 05:40:52 -0800 Subject: [PATCH 4/6] Pass const pointer to all netxcmd handlers Ensure buffer data is read-only and not modified by handler --- src/blua/liolib.c | 2 +- src/command.c | 43 ++++++++------- src/command.h | 4 +- src/d_clisrv.c | 24 ++++----- src/d_clisrv.h | 2 +- src/d_netcmd.c | 121 ++++++++++++++++++++++--------------------- src/d_netcmd.h | 2 +- src/d_netfil.h | 2 +- src/g_demo.c | 4 +- src/hu_stuff.c | 4 +- src/k_zvote.c | 8 +-- src/lua_consolelib.c | 2 +- src/lua_script.h | 2 +- src/p_saveg.c | 2 +- src/s_sound.c | 4 +- 15 files changed, 116 insertions(+), 110 deletions(-) diff --git a/src/blua/liolib.c b/src/blua/liolib.c index 5eec97fb4..4ed64110b 100644 --- a/src/blua/liolib.c +++ b/src/blua/liolib.c @@ -261,7 +261,7 @@ static int io_openlocal (lua_State *L) { } -void Got_LuaFile(UINT8 **cp, INT32 playernum) +void Got_LuaFile(const UINT8 **cp, INT32 playernum) { FILE **pf = NULL; UINT8 success = READUINT8(*cp); // The first (and only) byte indicates whether the file could be opened diff --git a/src/command.c b/src/command.c index 4a360018a..932730349 100644 --- a/src/command.c +++ b/src/command.c @@ -341,7 +341,7 @@ static const char *com_null_string = ""; static char *com_args = NULL; // current command args or NULL static int com_flags; -static void Got_NetVar(UINT8 **p, INT32 playernum); +static void Got_NetVar(const UINT8 **p, INT32 playernum); /** Initializes command buffer and adds basic commands. */ @@ -1749,16 +1749,16 @@ badinput: static boolean serverloading = false; static consvar_t * -ReadNetVar (UINT8 **p, char **return_value, boolean *return_stealth) +ReadNetVar (const UINT8 **p, const char **return_value, boolean *return_stealth) { UINT16 netid; - char *val; + const char *val; boolean stealth; consvar_t *cvar; netid = READUINT16 (*p); - val = (char *)*p; + val = (const char *)*p; SKIPSTRING (*p); stealth = READUINT8 (*p); @@ -1778,17 +1778,17 @@ ReadNetVar (UINT8 **p, char **return_value, boolean *return_stealth) } static consvar_t * -ReadDemoVar (UINT8 **p, char **return_value, boolean *return_stealth) +ReadDemoVar (const UINT8 **p, const char **return_value, boolean *return_stealth) { - char *name; - char *val; + const char *name; + const char *val; boolean stealth; consvar_t *cvar; - name = (char *)*p; + name = (const char *)*p; SKIPSTRING (*p); - val = (char *)*p; + val = (const char *)*p; SKIPSTRING (*p); stealth = READUINT8 (*p); @@ -1805,10 +1805,10 @@ ReadDemoVar (UINT8 **p, char **return_value, boolean *return_stealth) return cvar; } -static void Got_NetVar(UINT8 **p, INT32 playernum) +static void Got_NetVar(const UINT8 **p, INT32 playernum) { consvar_t *cvar; - char *svalue; + const char *svalue; boolean stealth; if (playernum != serverplayer && !IsPlayerAdmin(playernum) && !serverloading) @@ -1858,15 +1858,16 @@ void CV_SaveVars(UINT8 **p, boolean in_demo) WRITEUINT16(count_p, count); } -static void CV_LoadVars(UINT8 **p, - consvar_t *(*got)(UINT8 **p, char **ret_value, boolean *ret_stealth)) +static size_t CV_LoadVars(const UINT8 *bufstart, + consvar_t *(*got)(const UINT8 **p, const char **ret_value, boolean *ret_stealth)) { + const UINT8 *p = bufstart; const boolean store = (client || demo.playback); consvar_t *cvar; UINT16 count; - char *val; + const char *val; boolean stealth; // prevent "invalid command received" @@ -1887,16 +1888,18 @@ static void CV_LoadVars(UINT8 **p, } } - count = READUINT16(*p); + count = READUINT16(p); while (count--) { - cvar = (*got)(p, &val, &stealth); + cvar = (*got)(&p, &val, &stealth); if (cvar) Setvalue(cvar, val, stealth); } serverloading = false; + + return p - bufstart; } void CV_RevertNetVars(void) @@ -1928,14 +1931,14 @@ void CV_RevertNetVars(void) } } -void CV_LoadNetVars(UINT8 **p) +size_t CV_LoadNetVars(const UINT8 *p) { - CV_LoadVars(p, ReadNetVar); + return CV_LoadVars(p, ReadNetVar); } -void CV_LoadDemoVars(UINT8 **p) +size_t CV_LoadDemoVars(const UINT8 *p) { - CV_LoadVars(p, ReadDemoVar); + return CV_LoadVars(p, ReadDemoVar); } static void CV_SetCVar(consvar_t *var, const char *value, boolean stealth); diff --git a/src/command.h b/src/command.h index b8d71bb1f..74fc49708 100644 --- a/src/command.h +++ b/src/command.h @@ -281,13 +281,13 @@ void CV_SaveVariables(FILE *f); void CV_SaveVars(UINT8 **p, boolean in_demo); #define CV_SaveNetVars(p) CV_SaveVars(p, false) -void CV_LoadNetVars(UINT8 **p); +size_t CV_LoadNetVars(const UINT8 *p); // then revert after leaving a netgame void CV_RevertNetVars(void); #define CV_SaveDemoVars(p) CV_SaveVars(p, true) -void CV_LoadDemoVars(UINT8 **p); +size_t CV_LoadDemoVars(const UINT8 *p); // reset cheat netvars after cheats is deactivated void CV_CheatsChanged(void); diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 9030f562e..224a6d8ae 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -320,9 +320,9 @@ tic_t ExpandTics(INT32 low, tic_t basetic) // Some extra data function for handle textcmd buffer // ----------------------------------------------------------------- -static void (*listnetxcmd[MAXNETXCMD])(UINT8 **p, INT32 playernum); +static void (*listnetxcmd[MAXNETXCMD])(const UINT8 **p, INT32 playernum); -void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum)) +void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(const UINT8 **p, INT32 playernum)) { #ifdef PARANOIA if (id >= MAXNETXCMD) @@ -463,12 +463,12 @@ static boolean ExtraDataTicker(void) { if (playeringame[i] || i == 0) { - UINT8 *bufferstart = D_GetExistingTextcmd(gametic, i); + const UINT8 *bufferstart = D_GetExistingTextcmd(gametic, i); if (bufferstart) { - UINT8 *curpos = bufferstart; - UINT8 *bufferend = &curpos[((UINT16*)curpos)[0]+2]; + const UINT8 *curpos = bufferstart; + const UINT8 *bufferend = &curpos[((const UINT16*)curpos)[0]+2]; curpos += 2; while (curpos < bufferend) @@ -2825,7 +2825,7 @@ static void Command_Kick(void) CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); } -static void Got_KickCmd(UINT8 **p, INT32 playernum) +static void Got_KickCmd(const UINT8 **p, INT32 playernum) { INT32 pnum, msg; char buf[3 + MAX_REASONLENGTH]; @@ -3195,9 +3195,9 @@ static void Command_ResendGamestate(void) } } -static void Got_AddPlayer(UINT8 **p, INT32 playernum); -static void Got_RemovePlayer(UINT8 **p, INT32 playernum); -static void Got_AddBot(UINT8 **p, INT32 playernum); +static void Got_AddPlayer(const UINT8 **p, INT32 playernum); +static void Got_RemovePlayer(const UINT8 **p, INT32 playernum); +static void Got_AddBot(const UINT8 **p, INT32 playernum); void Joinable_OnChange(void); void Joinable_OnChange(void) @@ -3457,7 +3457,7 @@ static inline void SV_AddNode(INT32 node) } // Xcmd XD_ADDPLAYER -static void Got_AddPlayer(UINT8 **p, INT32 playernum) +static void Got_AddPlayer(const UINT8 **p, INT32 playernum) { INT16 node, newplayernum; UINT8 console; @@ -3566,7 +3566,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) } // Xcmd XD_REMOVEPLAYER -static void Got_RemovePlayer(UINT8 **p, INT32 playernum) +static void Got_RemovePlayer(const UINT8 **p, INT32 playernum) { SINT8 pnum, reason; @@ -3593,7 +3593,7 @@ static void Got_RemovePlayer(UINT8 **p, INT32 playernum) // Xcmd XD_ADDBOT // Compacted version of XD_ADDPLAYER for simplicity -static void Got_AddBot(UINT8 **p, INT32 playernum) +static void Got_AddBot(const UINT8 **p, INT32 playernum) { INT16 newplayernum; UINT8 skinnum = 0; diff --git a/src/d_clisrv.h b/src/d_clisrv.h index a237cce7e..b75c26386 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -582,7 +582,7 @@ void GenerateChallenge(uint8_t *buf); shouldsign_t ShouldSignChallenge(uint8_t *message); // Initialise the other field -void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum)); +void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(const UINT8 **p, INT32 playernum)); void SendNetXCmdForPlayer(UINT8 playerid, netxcmd_t id, const void *param, size_t nparam); #define SendNetXCmd(id, param, nparam) SendNetXCmdForPlayer(0, id, param, nparam) // Shortcut for P1 void SendKick(UINT8 playernum, UINT8 msg); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 812de6e5d..c7678f754 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -84,31 +84,31 @@ // protos // ------ -static void Got_NameAndColor(UINT8 **cp, INT32 playernum); -static void Got_WeaponPref(UINT8 **cp, INT32 playernum); -static void Got_PartyInvite(UINT8 **cp, INT32 playernum); -static void Got_AcceptPartyInvite(UINT8 **cp, INT32 playernum); -static void Got_CancelPartyInvite(UINT8 **cp, INT32 playernum); -static void Got_LeaveParty(UINT8 **cp, INT32 playernum); -static void Got_Mapcmd(UINT8 **cp, INT32 playernum); -static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum); -static void Got_SetupVotecmd(UINT8 **cp, INT32 playernum); -static void Got_ModifyVotecmd(UINT8 **cp, INT32 playernum); -static void Got_PickVotecmd(UINT8 **cp, INT32 playernum); -static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum); -static void Got_Addfilecmd(UINT8 **cp, INT32 playernum); -static void Got_Pause(UINT8 **cp, INT32 playernum); -static void Got_RandomSeed(UINT8 **cp, INT32 playernum); -static void Got_RunSOCcmd(UINT8 **cp, INT32 playernum); -static void Got_Teamchange(UINT8 **cp, INT32 playernum); -static void Got_Clearscores(UINT8 **cp, INT32 playernum); -static void Got_DiscordInfo(UINT8 **cp, INT32 playernum); -static void Got_ScheduleTaskcmd(UINT8 **cp, INT32 playernum); -static void Got_ScheduleClearcmd(UINT8 **cp, INT32 playernum); -static void Got_Automatecmd(UINT8 **cp, INT32 playernum); -static void Got_RequestMapQueuecmd(UINT8 **cp, INT32 playernum); -static void Got_MapQueuecmd(UINT8 **cp, INT32 playernum); -static void Got_Cheat(UINT8 **cp, INT32 playernum); +static void Got_NameAndColor(const UINT8 **cp, INT32 playernum); +static void Got_WeaponPref(const UINT8 **cp, INT32 playernum); +static void Got_PartyInvite(const UINT8 **cp, INT32 playernum); +static void Got_AcceptPartyInvite(const UINT8 **cp, INT32 playernum); +static void Got_CancelPartyInvite(const UINT8 **cp, INT32 playernum); +static void Got_LeaveParty(const UINT8 **cp, INT32 playernum); +static void Got_Mapcmd(const UINT8 **cp, INT32 playernum); +static void Got_ExitLevelcmd(const UINT8 **cp, INT32 playernum); +static void Got_SetupVotecmd(const UINT8 **cp, INT32 playernum); +static void Got_ModifyVotecmd(const UINT8 **cp, INT32 playernum); +static void Got_PickVotecmd(const UINT8 **cp, INT32 playernum); +static void Got_RequestAddfilecmd(const UINT8 **cp, INT32 playernum); +static void Got_Addfilecmd(const UINT8 **cp, INT32 playernum); +static void Got_Pause(const UINT8 **cp, INT32 playernum); +static void Got_RandomSeed(const UINT8 **cp, INT32 playernum); +static void Got_RunSOCcmd(const UINT8 **cp, INT32 playernum); +static void Got_Teamchange(const UINT8 **cp, INT32 playernum); +static void Got_Clearscores(const UINT8 **cp, INT32 playernum); +static void Got_DiscordInfo(const UINT8 **cp, INT32 playernum); +static void Got_ScheduleTaskcmd(const UINT8 **cp, INT32 playernum); +static void Got_ScheduleClearcmd(const UINT8 **cp, INT32 playernum); +static void Got_Automatecmd(const UINT8 **cp, INT32 playernum); +static void Got_RequestMapQueuecmd(const UINT8 **cp, INT32 playernum); +static void Got_MapQueuecmd(const UINT8 **cp, INT32 playernum); +static void Got_Cheat(const UINT8 **cp, INT32 playernum); static void Command_Playdemo_f(void); static void Command_Timedemo_f(void); @@ -165,12 +165,12 @@ static void Command_Clearscores_f(void); // Remote Administration static void Command_Changepassword_f(void); static void Command_Login_f(void); -static void Got_Verification(UINT8 **cp, INT32 playernum); -static void Got_Removal(UINT8 **cp, INT32 playernum); +static void Got_Verification(const UINT8 **cp, INT32 playernum); +static void Got_Removal(const UINT8 **cp, INT32 playernum); static void Command_Verify_f(void); static void Command_RemoveAdmin_f(void); static void Command_MotD_f(void); -static void Got_MotD_f(UINT8 **cp, INT32 playernum); +static void Got_MotD_f(const UINT8 **cp, INT32 playernum); static void Command_ShowScores_f(void); static void Command_ShowTime_f(void); @@ -1094,7 +1094,7 @@ static void FinalisePlaystateChange(INT32 playernum) P_CheckRacers(); // also SRB2Kart } -static void Got_NameAndColor(UINT8 **cp, INT32 playernum) +static void Got_NameAndColor(const UINT8 **cp, INT32 playernum) { player_t *p = &players[playernum]; char name[MAXPLAYERNAME+1]; @@ -1278,11 +1278,12 @@ void WeaponPref_Save(UINT8 **cp, INT32 playernum) WRITEUINT8(*cp, prefs); } -void WeaponPref_Parse(UINT8 **cp, INT32 playernum) +size_t WeaponPref_Parse(const UINT8 *bufstart, INT32 playernum) { + const UINT8 *p = bufstart; player_t *player = &players[playernum]; - UINT8 prefs = READUINT8(*cp); + UINT8 prefs = READUINT8(p); player->pflags &= ~(PF_KICKSTARTACCEL|PF_SHRINKME|PF_AUTOROULETTE); @@ -1302,17 +1303,19 @@ void WeaponPref_Parse(UINT8 **cp, INT32 playernum) // so this will have to do. K_UpdateShrinkCheat(player); } + + return p - bufstart; } -static void Got_WeaponPref(UINT8 **cp,INT32 playernum) +static void Got_WeaponPref(const UINT8 **cp,INT32 playernum) { - WeaponPref_Parse(cp, playernum); + *cp += WeaponPref_Parse(*cp, playernum); // SEE ALSO g_demo.c demo_extradata[playernum] |= DXD_WEAPONPREF; } -static void Got_PartyInvite(UINT8 **cp,INT32 playernum) +static void Got_PartyInvite(const UINT8 **cp,INT32 playernum) { UINT8 invitee; @@ -1356,7 +1359,7 @@ static void Got_PartyInvite(UINT8 **cp,INT32 playernum) } } -static void Got_AcceptPartyInvite(UINT8 **cp,INT32 playernum) +static void Got_AcceptPartyInvite(const UINT8 **cp,INT32 playernum) { int invitation; @@ -1397,7 +1400,7 @@ static void Got_AcceptPartyInvite(UINT8 **cp,INT32 playernum) } } -static void Got_CancelPartyInvite(UINT8 **cp,INT32 playernum) +static void Got_CancelPartyInvite(const UINT8 **cp,INT32 playernum) { UINT8 invitee; @@ -1427,7 +1430,7 @@ static void Got_CancelPartyInvite(UINT8 **cp,INT32 playernum) } } -static void Got_LeaveParty(UINT8 **cp,INT32 playernum) +static void Got_LeaveParty(const UINT8 **cp,INT32 playernum) { (void)cp; @@ -2700,7 +2703,7 @@ static void Command_Map_f(void) * ::serverplayer or ::adminplayer. * \sa D_MapChange */ -static void Got_Mapcmd(UINT8 **cp, INT32 playernum) +static void Got_Mapcmd(const UINT8 **cp, INT32 playernum) { UINT8 flags; INT32 presetplayer = 1; @@ -3113,7 +3116,7 @@ static void Command_QueueMap_f(void) Z_Free(mapname); } -static void Got_RequestMapQueuecmd(UINT8 **cp, INT32 playernum) +static void Got_RequestMapQueuecmd(const UINT8 **cp, INT32 playernum) { UINT8 flags; boolean setencore; @@ -3158,7 +3161,7 @@ static void Got_RequestMapQueuecmd(UINT8 **cp, INT32 playernum) Handle_MapQueueSend(mapnumber, setgametype, setencore); } -static void Got_MapQueuecmd(UINT8 **cp, INT32 playernum) +static void Got_MapQueuecmd(const UINT8 **cp, INT32 playernum) { UINT8 flags, queueposition, i; boolean setencore; @@ -3260,7 +3263,7 @@ static void Command_Pause(void) CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); } -static void Got_Pause(UINT8 **cp, INT32 playernum) +static void Got_Pause(const UINT8 **cp, INT32 playernum) { UINT8 dedicatedpause = false; const char *playername; @@ -3321,7 +3324,7 @@ static void Got_Pause(UINT8 **cp, INT32 playernum) * \param playernum Player responsible for the message. Must be ::serverplayer. * \author Graue */ -static void Got_RandomSeed(UINT8 **cp, INT32 playernum) +static void Got_RandomSeed(const UINT8 **cp, INT32 playernum) { UINT32 seed; @@ -3358,7 +3361,7 @@ static void Command_Clearscores_f(void) * \sa XD_CLEARSCORES, Command_Clearscores_f * \author SSNTails */ -static void Got_Clearscores(UINT8 **cp, INT32 playernum) +static void Got_Clearscores(const UINT8 **cp, INT32 playernum) { INT32 i; @@ -3608,7 +3611,7 @@ void P_SetPlayerSpectator(INT32 playernum) } //todo: This and the other teamchange functions are getting too long and messy. Needs cleaning. -static void Got_Teamchange(UINT8 **cp, INT32 playernum) +static void Got_Teamchange(const UINT8 **cp, INT32 playernum) { changeteam_union NetPacket; boolean error = false, wasspectator = false; @@ -3895,7 +3898,7 @@ static void Command_Verify_f(void) SendNetXCmd(XD_VERIFIED, buf, 1); } -static void Got_Verification(UINT8 **cp, INT32 playernum) +static void Got_Verification(const UINT8 **cp, INT32 playernum) { INT16 num = READUINT8(*cp); @@ -3945,7 +3948,7 @@ static void Command_RemoveAdmin_f(void) SendNetXCmd(XD_DEMOTED, buf, 1); } -static void Got_Removal(UINT8 **cp, INT32 playernum) +static void Got_Removal(const UINT8 **cp, INT32 playernum) { UINT8 num = READUINT8(*cp); @@ -4224,7 +4227,7 @@ static void Command_MotD_f(void) Z_Free(mymotd); } -static void Got_MotD_f(UINT8 **cp, INT32 playernum) +static void Got_MotD_f(const UINT8 **cp, INT32 playernum) { char *mymotd = Z_Malloc(sizeof(motd), PU_STATIC, NULL); INT32 i; @@ -4288,7 +4291,7 @@ static void Command_RunSOC(void) SendNetXCmd(XD_RUNSOC, buf, length); } -static void Got_RunSOCcmd(UINT8 **cp, INT32 playernum) +static void Got_RunSOCcmd(const UINT8 **cp, INT32 playernum) { char filename[256]; filestatus_t ncs = FS_NOTCHECKED; @@ -4480,7 +4483,7 @@ static void Command_Addfile(void) #endif/*TESTERS*/ } -static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum) +static void Got_RequestAddfilecmd(const UINT8 **cp, INT32 playernum) { char filename[241]; filestatus_t ncs = FS_NOTCHECKED; @@ -4539,7 +4542,7 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum) COM_BufAddText(va("addfile %s\n", filename)); } -static void Got_Addfilecmd(UINT8 **cp, INT32 playernum) +static void Got_Addfilecmd(const UINT8 **cp, INT32 playernum) { char filename[241]; filestatus_t ncs = FS_NOTCHECKED; @@ -5635,7 +5638,7 @@ static void Command_ExitLevel_f(void) } } -static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum) +static void Got_ExitLevelcmd(const UINT8 **cp, INT32 playernum) { (void)cp; @@ -5657,7 +5660,7 @@ static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum) G_FinishExitLevel(); } -static void Got_SetupVotecmd(UINT8 **cp, INT32 playernum) +static void Got_SetupVotecmd(const UINT8 **cp, INT32 playernum) { INT16 newGametype = 0; boolean baseEncore = false; @@ -5732,7 +5735,7 @@ static void Got_SetupVotecmd(UINT8 **cp, INT32 playernum) Y_StartVote(); } -static void Got_ModifyVotecmd(UINT8 **cp, INT32 playernum) +static void Got_ModifyVotecmd(const UINT8 **cp, INT32 playernum) { UINT8 targetID = READUINT8(*cp); SINT8 vote = READSINT8(*cp); @@ -5778,7 +5781,7 @@ fail: } } -static void Got_PickVotecmd(UINT8 **cp, INT32 playernum) +static void Got_PickVotecmd(const UINT8 **cp, INT32 playernum) { SINT8 pick = READSINT8(*cp); SINT8 level = READSINT8(*cp); @@ -5794,7 +5797,7 @@ static void Got_PickVotecmd(UINT8 **cp, INT32 playernum) Y_SetupVoteFinish(pick, level); } -static void Got_ScheduleTaskcmd(UINT8 **cp, INT32 playernum) +static void Got_ScheduleTaskcmd(const UINT8 **cp, INT32 playernum) { char command[MAXTEXTCMD]; INT16 seconds; @@ -5824,7 +5827,7 @@ static void Got_ScheduleTaskcmd(UINT8 **cp, INT32 playernum) } } -static void Got_ScheduleClearcmd(UINT8 **cp, INT32 playernum) +static void Got_ScheduleClearcmd(const UINT8 **cp, INT32 playernum) { (void)cp; @@ -5846,7 +5849,7 @@ static void Got_ScheduleClearcmd(UINT8 **cp, INT32 playernum) } } -static void Got_Automatecmd(UINT8 **cp, INT32 playernum) +static void Got_Automatecmd(const UINT8 **cp, INT32 playernum) { UINT8 eventID; char command[MAXTEXTCMD]; @@ -5889,7 +5892,7 @@ static void Got_Automatecmd(UINT8 **cp, INT32 playernum) } } -static void Got_Cheat(UINT8 **cp, INT32 playernum) +static void Got_Cheat(const UINT8 **cp, INT32 playernum) { UINT8 targetPlayer = READUINT8(*cp); cheat_t cheat = READUINT8(*cp); @@ -7125,7 +7128,7 @@ void LiveStudioAudience_OnChange(void) livestudioaudience_timer = 90; } -void Got_DiscordInfo(UINT8 **p, INT32 playernum) +void Got_DiscordInfo(const UINT8 **p, INT32 playernum) { if (playernum != serverplayer /*&& !IsPlayerAdmin(playernum)*/) { diff --git a/src/d_netcmd.h b/src/d_netcmd.h index b3b58de8b..d1d0fa643 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -236,7 +236,7 @@ void CleanupPlayerName(INT32 playernum, const char *newname); boolean EnsurePlayerNameIsGood(char *name, INT32 playernum); void WeaponPref_Send(UINT8 ssplayer); void WeaponPref_Save(UINT8 **cp, INT32 playernum); -void WeaponPref_Parse(UINT8 **cp, INT32 playernum); +size_t WeaponPref_Parse(const UINT8 *p, INT32 playernum); void D_SendPlayerConfig(UINT8 n); void Command_ExitGame_f(void); void Command_Retry_f(void); diff --git a/src/d_netfil.h b/src/d_netfil.h index fb5a6d29a..904dc0da5 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -142,7 +142,7 @@ void RemoveLuaFileTransfer(void); void RemoveAllLuaFileTransfers(void); void SV_AbortLuaFileTransfer(INT32 node); void CL_PrepareDownloadLuaFile(void); -void Got_LuaFile(UINT8 **cp, INT32 playernum); +void Got_LuaFile(const UINT8 **cp, INT32 playernum); void StoreLuaFileCallback(INT32 id); void RemoveLuaFileCallback(INT32 id); void MakePathDirs(char *path); diff --git a/src/g_demo.c b/src/g_demo.c index 95ebc454a..d84b780a6 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -331,7 +331,7 @@ void G_ReadDemoExtraData(void) } if (extradata & DXD_WEAPONPREF) { - WeaponPref_Parse(&demobuf.p, p); + demobuf.p += WeaponPref_Parse(demobuf.p, p); //CONS_Printf("weaponpref is %d for player %d\n", i, p); } @@ -3039,7 +3039,7 @@ void G_DoPlayDemo(const char *defdemoname) } // net var data - CV_LoadDemoVars(&demobuf.p); + demobuf.p += CV_LoadDemoVars(demobuf.p); // Sigh ... it's an empty demo. if (*demobuf.p == DEMOMARKER) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 74a2a8ff0..a889702dd 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -183,7 +183,7 @@ static void Command_Sayto_f(void); static void Command_Sayteam_f(void); static void Command_CSay_f(void); static void Command_Shout(void); -static void Got_Saycmd(UINT8 **p, INT32 playernum); +static void Got_Saycmd(const UINT8 **p, INT32 playernum); void HU_LoadGraphics(void) { @@ -660,7 +660,7 @@ static void Command_Shout(void) * \sa DoSayPacket * \author Graue */ -static void Got_Saycmd(UINT8 **p, INT32 playernum) +static void Got_Saycmd(const UINT8 **p, INT32 playernum) { SINT8 target; UINT8 flags; diff --git a/src/k_zvote.c b/src/k_zvote.c index 017163c05..535508c43 100644 --- a/src/k_zvote.c +++ b/src/k_zvote.c @@ -233,7 +233,7 @@ void K_SendCallMidVote(midVoteType_e voteType, INT32 voteVariable) } /*-------------------------------------------------- - static void Got_CallZVote(UINT8 **cp, INT32 playernum) + static void Got_CallZVote(const UINT8 **cp, INT32 playernum) Callback function for XD_CALLZVOTE NetXCmd. Attempts to start a new vote using K_InitNewMidVote. @@ -245,7 +245,7 @@ void K_SendCallMidVote(midVoteType_e voteType, INT32 voteVariable) Return:- N/A --------------------------------------------------*/ -static void Got_CallZVote(UINT8 **cp, INT32 playernum) +static void Got_CallZVote(const UINT8 **cp, INT32 playernum) { midVoteType_e type = MVT__MAX; INT32 variable = 0; @@ -288,7 +288,7 @@ static void K_PlayerSendMidVote(const UINT8 id) } /*-------------------------------------------------- - static void Got_SetZVote(UINT8 **cp, INT32 playernum) + static void Got_SetZVote(const UINT8 **cp, INT32 playernum) Callback function for XD_SETZVOTE NetXCmd. Updates the vote table. @@ -300,7 +300,7 @@ static void K_PlayerSendMidVote(const UINT8 id) Return:- N/A --------------------------------------------------*/ -static void Got_SetZVote(UINT8 **cp, INT32 playernum) +static void Got_SetZVote(const UINT8 **cp, INT32 playernum) { (void)cp; diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 98591bec9..126a75a38 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -36,7 +36,7 @@ static void clear_lua_stack(void) lua_settop(gL, 0); // clear stack } -void Got_Luacmd(UINT8 **cp, INT32 playernum) +void Got_Luacmd(const UINT8 **cp, INT32 playernum) { UINT8 i, argc, flags; char buf[256]; diff --git a/src/lua_script.h b/src/lua_script.h index 9e59d4d6d..231aa31a9 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -63,7 +63,7 @@ void LUA_UnArchive(savebuffer_t *save, boolean network); int LUA_PushGlobals(lua_State *L, const char *word); int LUA_WriteGlobals(lua_State *L, const char *word); -void Got_Luacmd(UINT8 **cp, INT32 playernum); // lua_consolelib.c +void Got_Luacmd(const UINT8 **cp, INT32 playernum); // lua_consolelib.c void LUA_CVarChanged(void *cvar); // lua_consolelib.c int Lua_optoption(lua_State *L, int narg, const char *def, const char *const lst[]); diff --git a/src/p_saveg.c b/src/p_saveg.c index 1ed3801b0..07373edc6 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -6929,7 +6929,7 @@ boolean P_LoadNetGame(savebuffer_t *save, boolean reloading) current_savebuffer = save; - CV_LoadNetVars(&save->p); + save->p += CV_LoadNetVars(save->p); if (!P_NetUnArchiveMisc(save, reloading)) return false; diff --git a/src/s_sound.c b/src/s_sound.c index eb5f8b020..c3cf0a64e 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -45,7 +45,7 @@ static boolean S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, static void Command_Tunes_f(void); static void Command_RestartAudio_f(void); static void Command_PlaySound(void); -static void Got_PlaySound(UINT8 **p, INT32 playernum); +static void Got_PlaySound(const UINT8 **p, INT32 playernum); static void Command_MusicDef_f(void); void Captioning_OnChange(void); @@ -2414,7 +2414,7 @@ static void Command_PlaySound(void) SendNetXCmd(XD_PLAYSOUND, buf, buf_p - buf); } -static void Got_PlaySound(UINT8 **cp, INT32 playernum) +static void Got_PlaySound(const UINT8 **cp, INT32 playernum) { INT32 sound_id = READINT32(*cp); From 63ff2f3f661bbbfbe3fcdac186b4d8bbe0a74026 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Sun, 11 Feb 2024 15:10:51 -0600 Subject: [PATCH 5/6] Check Lua stack before pushing cons args Prevents a Lua stack overrun when executing absurd console commands for local-only lua commands. --- src/lua_consolelib.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 98591bec9..d1e5219aa 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -187,6 +187,11 @@ void COM_Lua_f(void) I_Assert(lua_isfunction(gL, -1)); lua_remove(gL, -2); // pop command info table + if (!lua_checkstack(gL, COM_Argc() + 1)) + { + CONS_Alert(CONS_WARNING, "lua command stack overflow (%d, need %s more)\n", lua_gettop(gL), sizeu1(COM_Argc() + 1)); + return; + } LUA_PushUserdata(gL, &players[playernum], META_PLAYER); for (i = 1; i < COM_Argc(); i++) lua_pushstring(gL, COM_Argv(i)); From c0a6d20cec77c32c64ed3642d6eb64f37d0412e0 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 11 Feb 2024 15:40:04 -0800 Subject: [PATCH 6/6] Got_Luacmd: always read netxcmd data, even if command is not executed --- src/lua_consolelib.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index d1e5219aa..982736ff8 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -39,8 +39,18 @@ static void clear_lua_stack(void) void Got_Luacmd(UINT8 **cp, INT32 playernum) { UINT8 i, argc, flags; + const char *argv[256]; char buf[256]; + argc = READUINT8(*cp); + argv[0] = (const char*)*cp; + SKIPSTRINGN(*cp, 255); + for (i = 1; i < argc; i++) + { + argv[i] = (const char*)*cp; + SKIPSTRINGN(*cp, 255); + } + // don't use I_Assert here, goto the deny code below // to clean up and kick people who try nefarious exploits // like sending random junk lua commands to crash the server @@ -53,8 +63,7 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum) lua_getfield(gL, LUA_REGISTRYINDEX, "COM_Command"); // push COM_Command if (!lua_istable(gL, -1)) goto deny; - argc = READUINT8(*cp); - READSTRINGN(*cp, buf, 255); + strlcpy(buf, argv[0], 255); strlwr(buf); // must lowercase buffer lua_getfield(gL, -1, buf); // push command info table if (!lua_istable(gL, -1)) goto deny; @@ -90,7 +99,7 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum) LUA_PushUserdata(gL, &players[playernum], META_PLAYER); for (i = 1; i < argc; i++) { - READSTRINGN(*cp, buf, 255); + strlcpy(buf, argv[i], 255); lua_pushstring(gL, buf); } LUA_Call(gL, (int)argc, 0, 1); // argc is 1-based, so this will cover the player we passed too.