Fix stack underflow: currently for each call

it pops always the same fixed number of arguments related to
instruction array size leading to underflow most of the time
since it s mostly less.
This commit is contained in:
David Carlier 2018-07-24 21:40:23 +01:00
parent 39e2113c73
commit de2971541b
16 changed files with 63 additions and 62 deletions

View file

@ -389,7 +389,7 @@ void CL_ShutdownCGame( void ) {
if ( !cgvm ) {
return;
}
VM_Call( cgvm, CG_SHUTDOWN );
VM_Call( cgvm, CG_SHUTDOWN, 0 );
VM_Free( cgvm );
cgvm = NULL;
}
@ -742,7 +742,7 @@ void CL_InitCGame( void ) {
// init for this gamestate
// use the lastExecutedServerCommand instead of the serverCommandSequence
// otherwise server commands sent just before a gamestate are dropped
VM_Call( cgvm, CG_INIT, clc.serverMessageSequence, clc.lastExecutedServerCommand, clc.clientNum );
VM_Call( cgvm, CG_INIT, 3, clc.serverMessageSequence, clc.lastExecutedServerCommand, clc.clientNum );
// reset any CVAR_CHEAT cvars registered by cgame
if ( !clc.demoplaying && !cl_connectedToCheatServer )
@ -782,7 +782,7 @@ qboolean CL_GameCommand( void ) {
return qfalse;
}
return VM_Call( cgvm, CG_CONSOLE_COMMAND );
return VM_Call( cgvm, CG_CONSOLE_COMMAND, 0 );
}
@ -793,7 +793,7 @@ CL_CGameRendering
=====================
*/
void CL_CGameRendering( stereoFrame_t stereo ) {
VM_Call( cgvm, CG_DRAW_ACTIVE_FRAME, cl.serverTime, stereo, clc.demoplaying );
VM_Call( cgvm, CG_DRAW_ACTIVE_FRAME, 3, cl.serverTime, stereo, clc.demoplaying );
VM_Debug( 0 );
}

View file

@ -1455,7 +1455,7 @@ int CIN_PlayCinematic( const char *arg, int x, int y, int w, int h, int systemBi
if (cinTable[currentHandle].alterGameState) {
// close the menu
if ( uivm ) {
VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_NONE );
VM_Call( uivm, UI_SET_ACTIVE_MENU, 1, UIMENU_NONE );
}
} else {
cinTable[currentHandle].playonwalls = cl_inGameVideo->integer;

View file

@ -126,7 +126,7 @@ Con_MessageMode3_f
================
*/
void Con_MessageMode3_f (void) {
chat_playerNum = VM_Call( cgvm, CG_CROSSHAIR_PLAYER );
chat_playerNum = VM_Call( cgvm, CG_CROSSHAIR_PLAYER, 0 );
if ( chat_playerNum < 0 || chat_playerNum >= MAX_CLIENTS ) {
chat_playerNum = -1;
return;
@ -143,7 +143,7 @@ Con_MessageMode4_f
================
*/
void Con_MessageMode4_f (void) {
chat_playerNum = VM_Call( cgvm, CG_LAST_ATTACKER );
chat_playerNum = VM_Call( cgvm, CG_LAST_ATTACKER, 0 );
if ( chat_playerNum < 0 || chat_playerNum >= MAX_CLIENTS ) {
chat_playerNum = -1;
return;

View file

@ -361,9 +361,9 @@ CL_MouseEvent
*/
void CL_MouseEvent( int dx, int dy, int time ) {
if ( Key_GetCatcher( ) & KEYCATCH_UI ) {
VM_Call( uivm, UI_MOUSE_EVENT, dx, dy );
VM_Call( uivm, UI_MOUSE_EVENT, 2, dx, dy );
} else if (Key_GetCatcher( ) & KEYCATCH_CGAME) {
VM_Call (cgvm, CG_MOUSE_EVENT, dx, dy);
VM_Call (cgvm, CG_MOUSE_EVENT, 2, dx, dy);
} else {
cl.mouseDx[cl.mouseIndex] += dx;
cl.mouseDy[cl.mouseIndex] += dy;

View file

@ -1282,23 +1282,23 @@ void CL_KeyDownEvent( int key, unsigned time )
// escape always gets out of CGAME stuff
if (Key_GetCatcher( ) & KEYCATCH_CGAME) {
Key_SetCatcher( Key_GetCatcher( ) & ~KEYCATCH_CGAME );
VM_Call (cgvm, CG_EVENT_HANDLING, CGAME_EVENT_NONE);
VM_Call (cgvm, CG_EVENT_HANDLING, 1, CGAME_EVENT_NONE);
return;
}
if ( !( Key_GetCatcher( ) & KEYCATCH_UI ) ) {
if ( clc.state == CA_ACTIVE && !clc.demoplaying ) {
VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_INGAME );
VM_Call( uivm, UI_SET_ACTIVE_MENU, 1, UIMENU_INGAME );
}
else if ( clc.state != CA_DISCONNECTED ) {
CL_Disconnect_f();
S_StopAllSounds();
VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_MAIN );
VM_Call( uivm, UI_SET_ACTIVE_MENU, 1, UIMENU_MAIN );
}
return;
}
VM_Call( uivm, UI_KEY_EVENT, key, qtrue );
VM_Call( uivm, UI_KEY_EVENT, 2, key, qtrue );
return;
}
@ -1310,11 +1310,11 @@ void CL_KeyDownEvent( int key, unsigned time )
Console_Key( key );
} else if ( Key_GetCatcher( ) & KEYCATCH_UI ) {
if ( uivm ) {
VM_Call( uivm, UI_KEY_EVENT, key, qtrue );
VM_Call( uivm, UI_KEY_EVENT, 2, key, qtrue );
}
} else if ( Key_GetCatcher( ) & KEYCATCH_CGAME ) {
if ( cgvm ) {
VM_Call( cgvm, CG_KEY_EVENT, key, qtrue );
VM_Call( cgvm, CG_KEY_EVENT, 2, key, qtrue );
}
} else if ( Key_GetCatcher( ) & KEYCATCH_MESSAGE ) {
Message_Key( key );
@ -1353,9 +1353,9 @@ void CL_KeyUpEvent( int key, unsigned time )
CL_ParseBinding( key, qfalse, time );
if ( Key_GetCatcher( ) & KEYCATCH_UI && uivm ) {
VM_Call( uivm, UI_KEY_EVENT, key, qfalse );
VM_Call( uivm, UI_KEY_EVENT, 2, key, qfalse );
} else if ( Key_GetCatcher( ) & KEYCATCH_CGAME && cgvm ) {
VM_Call( cgvm, CG_KEY_EVENT, key, qfalse );
VM_Call( cgvm, CG_KEY_EVENT, 2, key, qfalse );
}
}
@ -1394,7 +1394,7 @@ void CL_CharEvent( int key ) {
}
else if ( Key_GetCatcher( ) & KEYCATCH_UI )
{
VM_Call( uivm, UI_KEY_EVENT, key | K_CHAR_FLAG, qtrue );
VM_Call( uivm, UI_KEY_EVENT, 2, key | K_CHAR_FLAG, qtrue );
}
else if ( Key_GetCatcher( ) & KEYCATCH_MESSAGE )
{

View file

@ -359,12 +359,12 @@ void CL_VoipParseTargets(void)
{
if(!Q_stricmpn(target, "attacker", 8))
{
val = VM_Call(cgvm, CG_LAST_ATTACKER);
val = VM_Call(cgvm, CG_LAST_ATTACKER, 0);
target += 8;
}
else if(!Q_stricmpn(target, "crosshair", 9))
{
val = VM_Call(cgvm, CG_CROSSHAIR_PLAYER);
val = VM_Call(cgvm, CG_CROSSHAIR_PLAYER, 0);
target += 9;
}
else
@ -1429,7 +1429,7 @@ void CL_Disconnect( qboolean showMainMenu ) {
}
if ( uivm && showMainMenu ) {
VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_NONE );
VM_Call( uivm, UI_SET_ACTIVE_MENU, 1, UIMENU_NONE );
}
SCR_StopCinematic ();
@ -2956,12 +2956,12 @@ void CL_Frame ( int msec ) {
if ( cls.cddialog ) {
// bring up the cd error dialog if needed
cls.cddialog = qfalse;
VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_NEED_CD );
VM_Call( uivm, UI_SET_ACTIVE_MENU, 1, UIMENU_NEED_CD );
} else if ( clc.state == CA_DISCONNECTED && !( Key_GetCatcher( ) & KEYCATCH_UI )
&& !com_sv_running->integer && uivm ) {
// if disconnected, bring up the menu
S_StopAllSounds();
VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_MAIN );
VM_Call( uivm, UI_SET_ACTIVE_MENU, 1, UIMENU_MAIN );
}
// if recording an avi, lock to a fixed fps

View file

@ -477,7 +477,7 @@ void SCR_DrawScreenField( stereoFrame_t stereoFrame ) {
re.BeginFrame( stereoFrame );
uiFullscreen = (uivm && VM_Call( uivm, UI_IS_FULLSCREEN ));
uiFullscreen = (uivm && VM_Call( uivm, UI_IS_FULLSCREEN, 0 ));
// wide aspect ratio screens need to have the sides cleared
// unless they are displaying game renderings
@ -502,15 +502,15 @@ void SCR_DrawScreenField( stereoFrame_t stereoFrame ) {
case CA_DISCONNECTED:
// force menu up
S_StopAllSounds();
VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_MAIN );
VM_Call( uivm, UI_SET_ACTIVE_MENU, 1, UIMENU_MAIN );
break;
case CA_CONNECTING:
case CA_CHALLENGING:
case CA_CONNECTED:
// connecting clients will only show the connection dialog
// refresh to update the time
VM_Call( uivm, UI_REFRESH, cls.realtime );
VM_Call( uivm, UI_DRAW_CONNECT_SCREEN, qfalse );
VM_Call( uivm, UI_REFRESH, 1, cls.realtime );
VM_Call( uivm, UI_DRAW_CONNECT_SCREEN, 1, qfalse );
break;
case CA_LOADING:
case CA_PRIMED:
@ -520,8 +520,8 @@ void SCR_DrawScreenField( stereoFrame_t stereoFrame ) {
// also draw the connection information, so it doesn't
// flash away too briefly on local or lan games
// refresh to update the time
VM_Call( uivm, UI_REFRESH, cls.realtime );
VM_Call( uivm, UI_DRAW_CONNECT_SCREEN, qtrue );
VM_Call( uivm, UI_REFRESH, 1, cls.realtime );
VM_Call( uivm, UI_DRAW_CONNECT_SCREEN, 1, qtrue );
break;
case CA_ACTIVE:
// always supply STEREO_CENTER as vieworg offset is now done by the engine.
@ -536,7 +536,7 @@ void SCR_DrawScreenField( stereoFrame_t stereoFrame ) {
// the menu draws next
if ( Key_GetCatcher( ) & KEYCATCH_UI && uivm ) {
VM_Call( uivm, UI_REFRESH, cls.realtime );
VM_Call( uivm, UI_REFRESH, 1, cls.realtime );
}
// console draws next

View file

@ -1091,7 +1091,7 @@ void CL_ShutdownUI( void ) {
if ( !uivm ) {
return;
}
VM_Call( uivm, UI_SHUTDOWN );
VM_Call( uivm, UI_SHUTDOWN, 0 );
VM_Free( uivm );
uivm = NULL;
}
@ -1122,11 +1122,11 @@ void CL_InitUI( void ) {
}
// sanity check
v = VM_Call( uivm, UI_GETAPIVERSION );
v = VM_Call( uivm, UI_GETAPIVERSION, 0 );
if (v == UI_OLD_API_VERSION) {
// Com_Printf(S_COLOR_YELLOW "WARNING: loading old Quake III Arena User Interface version %d\n", v );
// init for this gamestate
VM_Call( uivm, UI_INIT, (clc.state >= CA_AUTHORIZING && clc.state < CA_ACTIVE));
VM_Call( uivm, UI_INIT, 1, (clc.state >= CA_AUTHORIZING && clc.state < CA_ACTIVE));
}
else if (v != UI_API_VERSION) {
// Free uivm now, so UI_SHUTDOWN doesn't get called later.
@ -1138,14 +1138,14 @@ void CL_InitUI( void ) {
}
else {
// init for this gamestate
VM_Call( uivm, UI_INIT, (clc.state >= CA_AUTHORIZING && clc.state < CA_ACTIVE) );
VM_Call( uivm, UI_INIT, 1, (clc.state >= CA_AUTHORIZING && clc.state < CA_ACTIVE) );
}
}
#ifndef STANDALONE
qboolean UI_usesUniqueCDKey( void ) {
if (uivm) {
return (VM_Call( uivm, UI_HASUNIQUECDKEY) == qtrue);
return (VM_Call( uivm, UI_HASUNIQUECDKEY, 0) == qtrue);
} else {
return qfalse;
}
@ -1164,5 +1164,5 @@ qboolean UI_GameCommand( void ) {
return qfalse;
}
return VM_Call( uivm, UI_CONSOLE_COMMAND, cls.realtime );
return VM_Call( uivm, UI_CONSOLE_COMMAND, 1, cls.realtime );
}

View file

@ -366,7 +366,7 @@ void VM_Forced_Unload_Start(void);
void VM_Forced_Unload_Done(void);
vm_t *VM_Restart(vm_t *vm, qboolean unpure);
intptr_t QDECL VM_Call( vm_t *vm, int callNum, ... );
intptr_t QDECL VM_Call( vm_t *vm, int callNum, int n, ... );
void VM_Debug( int level );

View file

@ -804,11 +804,11 @@ locals from sp
==============
*/
intptr_t QDECL VM_Call( vm_t *vm, int callnum, ... )
intptr_t QDECL VM_Call( vm_t *vm, int callnum, int n, ... )
{
vm_t *oldVM;
intptr_t r;
int i;
int i, cnt = n;
if(!vm || !vm->name[0])
Com_Error(ERR_FATAL, "VM_Call with NULL vm");
@ -827,8 +827,8 @@ intptr_t QDECL VM_Call( vm_t *vm, int callnum, ... )
//rcg010207 - see dissertation at top of VM_DllSyscall() in this file.
int args[MAX_VMMAIN_ARGS-1];
va_list ap;
va_start(ap, callnum);
for (i = 0; i < ARRAY_LEN(args); i++) {
va_start(ap, n);
for (i = 0; i < ARRAY_LEN(args) && cnt-- > 0; i++) {
args[i] = va_arg(ap, int);
}
va_end(ap);
@ -845,6 +845,7 @@ intptr_t QDECL VM_Call( vm_t *vm, int callnum, ... )
#endif
r = VM_CallInterpreted( vm, (int*)&callnum );
#else
cnt = n;
struct {
int callnum;
int args[MAX_VMMAIN_ARGS-1];
@ -852,8 +853,8 @@ intptr_t QDECL VM_Call( vm_t *vm, int callnum, ... )
va_list ap;
a.callnum = callnum;
va_start(ap, callnum);
for (i = 0; i < ARRAY_LEN(a.args); i++) {
va_start(ap, n);
for (i = 0; i < ARRAY_LEN(a.args) && cnt-- > 0; i++) {
a.args[i] = va_arg(ap, int);
}
va_end(ap);

View file

@ -435,7 +435,7 @@ void SV_BotFrame( int time ) {
if (!bot_enable) return;
//NOTE: maybe the game is already shutdown
if (!gvm) return;
VM_Call( gvm, BOTAI_START_FRAME, time );
VM_Call( gvm, BOTAI_START_FRAME, 1, time );
}
/*

View file

@ -302,7 +302,7 @@ static void SV_MapRestart_f( void ) {
// run a few frames to allow everything to settle
for (i = 0; i < 3; i++)
{
VM_Call (gvm, GAME_RUN_FRAME, sv.time);
VM_Call (gvm, GAME_RUN_FRAME, 1, sv.time);
sv.time += 100;
svs.time += 100;
}
@ -329,7 +329,7 @@ static void SV_MapRestart_f( void ) {
SV_AddServerCommand( client, "map_restart\n" );
// connect the client again, without the firstTime flag
denied = VM_ExplicitArgPtr( gvm, VM_Call( gvm, GAME_CLIENT_CONNECT, i, qfalse, isBot ) );
denied = VM_ExplicitArgPtr( gvm, VM_Call( gvm, GAME_CLIENT_CONNECT, 3, i, qfalse, isBot ) );
if ( denied ) {
// this generally shouldn't happen, because the client
// was connected before the level change
@ -350,7 +350,7 @@ static void SV_MapRestart_f( void ) {
}
// run another frame to allow things to look at all the players
VM_Call (gvm, GAME_RUN_FRAME, sv.time);
VM_Call (gvm, GAME_RUN_FRAME, 1, sv.time);
sv.time += 100;
svs.time += 100;
}

View file

@ -558,7 +558,7 @@ gotnewcl:
Q_strncpyz( newcl->userinfo, userinfo, sizeof(newcl->userinfo) );
// get the game a chance to reject this connection or modify the userinfo
denied = VM_Call( gvm, GAME_CLIENT_CONNECT, clientNum, qtrue, qfalse ); // firstTime = qtrue
denied = VM_Call( gvm, GAME_CLIENT_CONNECT, 3, clientNum, qtrue, qfalse ); // firstTime = qtrue
if ( denied ) {
// we can't just use VM_ArgPtr, because that is only valid inside a VM_Call
char *str = VM_ExplicitArgPtr( gvm, denied );
@ -664,7 +664,7 @@ void SV_DropClient( client_t *drop, const char *reason ) {
// call the prog function for removing a client
// this will remove the body, among other things
VM_Call( gvm, GAME_CLIENT_DISCONNECT, drop - svs.clients );
VM_Call( gvm, GAME_CLIENT_DISCONNECT, 1, drop - svs.clients );
// add the disconnect command
SV_SendServerCommand( drop, "disconnect \"%s\"", reason);
@ -803,7 +803,7 @@ void SV_ClientEnterWorld( client_t *client, usercmd_t *cmd ) {
memset(&client->lastUsercmd, '\0', sizeof(client->lastUsercmd));
// call the game begin function
VM_Call( gvm, GAME_CLIENT_BEGIN, client - svs.clients );
VM_Call( gvm, GAME_CLIENT_BEGIN, 1, client - svs.clients );
}
/*
@ -1492,7 +1492,7 @@ static void SV_UpdateUserinfo_f( client_t *cl ) {
SV_UserinfoChanged( cl );
// call prog code to allow overrides
VM_Call( gvm, GAME_CLIENT_USERINFO_CHANGED, cl - svs.clients );
VM_Call( gvm, GAME_CLIENT_USERINFO_CHANGED, 1, cl - svs.clients );
}
@ -1576,7 +1576,7 @@ void SV_ExecuteClientCommand( client_t *cl, const char *s, qboolean clientOK ) {
// pass unknown strings to the game
if (!u->name && sv.state == SS_GAME && (cl->state == CS_ACTIVE || cl->state == CS_PRIMED)) {
Cmd_Args_Sanitize();
VM_Call( gvm, GAME_CLIENT_COMMAND, cl - svs.clients );
VM_Call( gvm, GAME_CLIENT_COMMAND, 1, cl - svs.clients );
}
}
else if (!bProcessed)
@ -1656,7 +1656,7 @@ void SV_ClientThink (client_t *cl, usercmd_t *cmd) {
return; // may have been kicked during the last usercmd
}
VM_Call( gvm, GAME_CLIENT_THINK, cl - svs.clients );
VM_Call( gvm, GAME_CLIENT_THINK, 1, cl - svs.clients );
}
/*

View file

@ -860,7 +860,7 @@ void SV_ShutdownGameProgs( void ) {
if ( !gvm ) {
return;
}
VM_Call( gvm, GAME_SHUTDOWN, qfalse );
VM_Call( gvm, GAME_SHUTDOWN, 1, qfalse );
VM_Free( gvm );
gvm = NULL;
}
@ -888,7 +888,7 @@ static void SV_InitGameVM( qboolean restart ) {
// use the current msec count for a random seed
// init for this gamestate
VM_Call (gvm, GAME_INIT, sv.time, Com_Milliseconds(), restart);
VM_Call (gvm, GAME_INIT, 3, sv.time, Com_Milliseconds(), restart);
}
@ -904,7 +904,7 @@ void SV_RestartGameProgs( void ) {
if ( !gvm ) {
return;
}
VM_Call( gvm, GAME_SHUTDOWN, qtrue );
VM_Call( gvm, GAME_SHUTDOWN, 1, qtrue );
// do a restart instead of a free
gvm = VM_Restart(gvm, qtrue);
@ -958,6 +958,6 @@ qboolean SV_GameCommand( void ) {
return qfalse;
}
return VM_Call( gvm, GAME_CONSOLE_COMMAND );
return VM_Call( gvm, GAME_CONSOLE_COMMAND, 0 );
}

View file

@ -497,7 +497,7 @@ void SV_SpawnServer( char *server, qboolean killBots ) {
// run a few frames to allow everything to settle
for (i = 0;i < 3; i++)
{
VM_Call (gvm, GAME_RUN_FRAME, sv.time);
VM_Call (gvm, GAME_RUN_FRAME, 1, sv.time);
SV_BotFrame (sv.time);
sv.time += 100;
svs.time += 100;
@ -523,7 +523,7 @@ void SV_SpawnServer( char *server, qboolean killBots ) {
}
// connect the client again
denied = VM_ExplicitArgPtr( gvm, VM_Call( gvm, GAME_CLIENT_CONNECT, i, qfalse, isBot ) ); // firstTime = qfalse
denied = VM_ExplicitArgPtr( gvm, VM_Call( gvm, GAME_CLIENT_CONNECT, 3, i, qfalse, isBot ) ); // firstTime = qfalse
if ( denied ) {
// this generally shouldn't happen, because the client
// was connected before the level change
@ -547,14 +547,14 @@ void SV_SpawnServer( char *server, qboolean killBots ) {
client->deltaMessage = -1;
client->lastSnapshotTime = 0; // generate a snapshot immediately
VM_Call( gvm, GAME_CLIENT_BEGIN, i );
VM_Call( gvm, GAME_CLIENT_BEGIN, 1, i );
}
}
}
}
// run another frame to allow things to look at all the players
VM_Call (gvm, GAME_RUN_FRAME, sv.time);
VM_Call (gvm, GAME_RUN_FRAME, 1, sv.time);
SV_BotFrame (sv.time);
sv.time += 100;
svs.time += 100;

View file

@ -1140,7 +1140,7 @@ void SV_Frame( int msec ) {
sv.time += frameMsec;
// let everything in the world think and move
VM_Call (gvm, GAME_RUN_FRAME, sv.time);
VM_Call (gvm, GAME_RUN_FRAME, 1, sv.time);
}
if ( com_speeds->integer ) {