]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
Fix Windows-specific use-after-free causing crash after disconnecting
authorcloudwalk <cloudwalk@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 23 May 2020 22:22:30 +0000 (22:22 +0000)
committercloudwalk <cloudwalk@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 23 May 2020 22:22:30 +0000 (22:22 +0000)
This explicitly deregisters CSQC commands every time CSQC shuts down. This patch
also avoids Z_Malloc'ing the cmd names for each CSQC command and avoids forcing
a Cmd_AddCommand if the command exists.

CSQC was force-adding a command even if it already existed, and when it did,
it would pass a pointer from a mempool that would later get freed when
CSQC shuts down, and Windows' strcasecmp doesn't like dangling pointers.
The Z_Malloc wasn't much better because it could have caused a memory leak.
So the best solution was to only pass the pointer but make sure the commands
are freed when CSQC shuts down.

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@12558 d7cf8633-e32d-0410-b094-e92efae38249

clvm_cmds.c
cmd.c
cmd.h
csprogs.c
sbar.c

index 25f3b195a32441e89ae583875990eadcbb5c44cf..eb2976804639de1230ecfe83ce99029e13350724 100644 (file)
@@ -1623,20 +1623,9 @@ static void VM_CL_setlistener (prvm_prog_t *prog)
 //#352 void(string cmdname) registercommand (EXT_CSQC)
 static void VM_CL_registercmd (prvm_prog_t *prog)
 {
-       char *t;
        VM_SAFEPARMCOUNT(1, VM_CL_registercmd);
        if(!Cmd_Exists(&cmd_client, PRVM_G_STRING(OFS_PARM0)))
-       {
-               size_t alloclen;
-
-               alloclen = strlen(PRVM_G_STRING(OFS_PARM0)) + 1;
-               t = (char *)Z_Malloc(alloclen);
-               memcpy(t, PRVM_G_STRING(OFS_PARM0), alloclen);
-               Cmd_AddCommand(&cmd_client, t, NULL, "console command created by QuakeC");
-       }
-       else
                Cmd_AddCommand(&cmd_client, PRVM_G_STRING(OFS_PARM0), NULL, "console command created by QuakeC");
-
 }
 
 //#360 float() readbyte (EXT_CSQC)
diff --git a/cmd.c b/cmd.c
index 74f7eaff7674c2f3693298ce4f973295439f94eb..fedfb13dcbe52b86dfd7eaf0a2fcf8b7fe795ec7 100644 (file)
--- a/cmd.c
+++ b/cmd.c
@@ -1982,11 +1982,18 @@ const char **Cmd_CompleteAliasBuildList (cmd_state_t *cmd, const char *partial)
        return buf;
 }
 
-void Cmd_ClearCsqcFuncs (cmd_state_t *cmd)
+// TODO: Make this more generic?
+void Cmd_ClearCSQCCommands (cmd_state_t *cmd)
 {
        cmd_function_t *func;
-       for (func = cmd->userdefined->csqc_functions; func; func = func->next)
-               func->csqcfunc = false;
+       cmd_function_t **next = &cmd->userdefined->csqc_functions;
+       
+       while(*next)
+       {
+               func = *next;
+               *next = func->next;
+               Z_Free(func);
+       }
 }
 
 /*
diff --git a/cmd.h b/cmd.h
index 5a88ea918a794aeff3386188309f74ed9264d7da..98057fa82324419a9e4455e8f0c07894dde2f440 100644 (file)
--- a/cmd.h
+++ b/cmd.h
@@ -248,7 +248,7 @@ void Cmd_ForwardToServer_f (cmd_state_t *cmd);
 /// enclosing quote marks are also put.
 qboolean Cmd_QuoteString(char *out, size_t outlen, const char *in, const char *quoteset, qboolean putquotes);
 
-void Cmd_ClearCsqcFuncs (cmd_state_t *cmd);
+void Cmd_ClearCSQCCommands (cmd_state_t *cmd);
 
 #endif
 
index 3bc3495c7e0412f743099b175bf7b518c4f88319..fb37cba069df80f097eca368b59ecbab582eb7cd 100644 (file)
--- a/csprogs.c
+++ b/csprogs.c
@@ -1163,7 +1163,7 @@ void CL_VM_Init (void)
 void CL_VM_ShutDown (void)
 {
        prvm_prog_t *prog = CLVM_prog;
-       Cmd_ClearCsqcFuncs(&cmd_client);
+       Cmd_ClearCSQCCommands(&cmd_client);
        //Cvar_SetValueQuick(&csqc_progcrc, -1);
        //Cvar_SetValueQuick(&csqc_progsize, -1);
        if(!cl.csqc_loaded)
diff --git a/sbar.c b/sbar.c
index 40261c677c71829d4d9e99ab8ffd1bc341b161af..010925b7b6bf81cb63eb80c86dc55d3957b7917f 100644 (file)
--- a/sbar.c
+++ b/sbar.c
@@ -357,8 +357,11 @@ static void sbar_newmap(void)
 
 void Sbar_Init (void)
 {
-       Cmd_AddCommand(&cmd_client, "+showscores", Sbar_ShowScores_f, "show scoreboard");
-       Cmd_AddCommand(&cmd_client, "-showscores", Sbar_DontShowScores_f, "hide scoreboard");
+       if(gamemode == GAME_NORMAL) // Workaround so Quake doesn't trample on Xonotic.
+       {
+               Cmd_AddCommand(&cmd_client, "+showscores", Sbar_ShowScores_f, "show scoreboard");
+               Cmd_AddCommand(&cmd_client, "-showscores", Sbar_DontShowScores_f, "hide scoreboard");
+       }
        Cvar_RegisterVariable(&showfps);
        Cvar_RegisterVariable(&showsound);
        Cvar_RegisterVariable(&showblur);