]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
PRVM: optimise tempstring creation
authorbones_was_here <bones_was_here@xonotic.au>
Tue, 19 Dec 2023 13:19:21 +0000 (23:19 +1000)
committerbones_was_here <bones_was_here@xonotic.au>
Sun, 21 Jan 2024 11:07:51 +0000 (21:07 +1000)
No need for strlen in PRVM_SetTempString(), usually we already have that
information.

Signed-off-by: bones_was_here <bones_was_here@xonotic.au>
26 files changed:
cl_demo.c
cl_parse.c
client.h
clvm_cmds.c
cmd.c
cmd.h
com_msg.c
common.c
common.h
console.c
csprogs.c
csprogs.h
keys.c
lhnet.c
lhnet.h
menu.h
mvm_cmds.c
netconn.c
netconn.h
progsvm.h
prvm_cmds.c
prvm_cmds.h
prvm_edict.c
server.h
sv_user.c
svvm_cmds.c

index e67c1ab60dde9a3c19cdc3ee0d562566c5f6ec4c..a11d63b5ba33f5939dc7de352f4940d2e1b85030 100644 (file)
--- a/cl_demo.c
+++ b/cl_demo.c
@@ -348,6 +348,7 @@ void CL_Record_f(cmd_state_t *cmd)
        int c, track;
        char name[MAX_OSPATH];
        char vabuf[1024];
+       int vabuf_len;
 
        c = Cmd_Argc(cmd);
        if (c != 2 && c != 3 && c != 4)
@@ -386,7 +387,10 @@ void CL_Record_f(cmd_state_t *cmd)
 
        // start the map up
        if (c > 2)
-               Cmd_ExecuteString ( cmd, va(vabuf, sizeof(vabuf), "map %s", Cmd_Argv(cmd, 2)), src_local, false);
+       {
+               vabuf_len = dpsnprintf(vabuf, sizeof(vabuf), "map %s", Cmd_Argv(cmd, 2));
+               Cmd_ExecuteString(cmd, vabuf, vabuf_len, src_local, false);
+       }
 
        // open the demo file
        Con_Printf("recording to %s.\n", name);
index f2ec8630be6625a9409001b8ecc4c25051b1fc48..f02f63e169c147d5d3066f4b34e5e34d195f4c67 100644 (file)
@@ -3444,6 +3444,7 @@ void CL_ParseServerMessage(void)
        qbool   qwplayerupdatereceived;
        qbool   strip_pqc;
        char vabuf[1024];
+       size_t cl_readstring_len;
 
        // LadyHavoc: moved demo message writing from before the packet parse to
        // after the packet parse so that CL_Stop_f can be called by cl_autodemo
@@ -3550,22 +3551,28 @@ void CL_ParseServerMessage(void)
 
                        case qw_svc_print:
                                i = MSG_ReadByte(&cl_message);
-                               temp = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring));
+                               cl_readstring_len = MSG_ReadString_len(&cl_message, cl_readstring, sizeof(cl_readstring));
+                               temp = cl_readstring;
                                if (CL_ExaminePrintString(temp)) // look for anything interesting like player IP addresses or ping reports
                                {
                                        if (i == 3) // chat
-                                               CSQC_AddPrintText(va(vabuf, sizeof(vabuf), "\1%s", temp));      //[515]: csqc
+                                       {
+                                               cl_readstring_len = dpsnprintf(vabuf, sizeof(vabuf), "\1%s", temp);
+                                               CSQC_AddPrintText(vabuf, cl_readstring_len);    //[515]: csqc
+                                       }
                                        else
-                                               CSQC_AddPrintText(temp);
+                                               CSQC_AddPrintText(temp, cl_readstring_len);
                                }
                                break;
 
                        case qw_svc_centerprint:
-                               CL_VM_Parse_CenterPrint(MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)));     //[515]: csqc
+                               cl_readstring_len = MSG_ReadString_len(&cl_message, cl_readstring, sizeof(cl_readstring));
+                               CL_VM_Parse_CenterPrint(cl_readstring, cl_readstring_len);      //[515]: csqc
                                break;
 
                        case qw_svc_stufftext:
-                               CL_VM_Parse_StuffCmd(MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)));        //[515]: csqc
+                               cl_readstring_len = MSG_ReadString_len(&cl_message, cl_readstring, sizeof(cl_readstring));
+                               CL_VM_Parse_StuffCmd(cl_readstring, cl_readstring_len); //[515]: csqc
                                break;
 
                        case qw_svc_damage:
@@ -3708,7 +3715,7 @@ void CL_ParseServerMessage(void)
                                break;
 
                        case qw_svc_sellscreen:
-                               Cmd_ExecuteString(cmd_local, "help", src_local, true);
+                               Cmd_ExecuteString(cmd_local, "help", 4, src_local, true);
                                break;
 
                        case qw_svc_smallkick:
@@ -3920,17 +3927,20 @@ void CL_ParseServerMessage(void)
                                break;
 
                        case svc_print:
-                               temp = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring));
+                               cl_readstring_len = MSG_ReadString_len(&cl_message, cl_readstring, sizeof(cl_readstring));
+                               temp = cl_readstring;
                                if (CL_ExaminePrintString(temp)) // look for anything interesting like player IP addresses or ping reports
-                                       CSQC_AddPrintText(temp);        //[515]: csqc
+                                       CSQC_AddPrintText(temp, cl_readstring_len);     //[515]: csqc
                                break;
 
                        case svc_centerprint:
-                               CL_VM_Parse_CenterPrint(MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)));     //[515]: csqc
+                               cl_readstring_len = MSG_ReadString_len(&cl_message, cl_readstring, sizeof(cl_readstring));
+                               CL_VM_Parse_CenterPrint(cl_readstring, cl_readstring_len);      //[515]: csqc
                                break;
 
                        case svc_stufftext:
-                               temp = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring));
+                               cl_readstring_len = MSG_ReadString_len(&cl_message, cl_readstring, sizeof(cl_readstring));
+                               temp = cl_readstring;
                                /* if(utf8_enable.integer)
                                {
                                        strip_pqc = true;
@@ -3961,11 +3971,15 @@ void CL_ParseServerMessage(void)
                                        if(*temp == 0x01)
                                        {
                                                ++temp;
+                                               --cl_readstring_len;
                                                while(*temp >= 0x01 && *temp <= 0x1F)
+                                               {
                                                        ++temp;
+                                                       --cl_readstring_len;
+                                               }
                                        }
                                }
-                               CL_VM_Parse_StuffCmd(temp);     //[515]: csqc
+                               CL_VM_Parse_StuffCmd(temp, cl_readstring_len);  //[515]: csqc
                                break;
 
                        case svc_damage:
@@ -4204,7 +4218,7 @@ void CL_ParseServerMessage(void)
                                break;
 
                        case svc_sellscreen:
-                               Cmd_ExecuteString(cmd_local, "help", src_local, true);
+                               Cmd_ExecuteString(cmd_local, "help", 4, src_local, true);
                                break;
                        case svc_hidelmp:
                                if (gamemode == GAME_TENEBRAE)
index 02ac81ff35de02a1407dc236538649e33a6a08f9..bed786369e4ae230a0c9a8ae34bdeede4eef0172 100644 (file)
--- a/client.h
+++ b/client.h
@@ -1118,6 +1118,7 @@ typedef struct client_state_s
        qbool csqc_usecsqclistener;
        matrix4x4_t csqc_listenermatrix;
        char csqc_printtextbuf[MAX_INPUTLINE];
+       size_t csqc_printtextbuf_len; ///< strlen
 
        // collision culling data
        world_t world;
index 7a12027f45719c190cadbbc6cf6886a5d7800739..78039744ace4d58cc1b23f6f70428e592c29f60d 100644 (file)
@@ -2063,6 +2063,7 @@ static void VM_CL_getstats (prvm_prog_t *prog)
 {
        int i;
        char t[17];
+       size_t t_len;
        VM_SAFEPARMCOUNT(1, VM_CL_getstats);
        i = (int)PRVM_G_FLOAT(OFS_PARM0);
        if(i < 0 || i > MAX_CL_STATS-4)
@@ -2071,8 +2072,8 @@ static void VM_CL_getstats (prvm_prog_t *prog)
                VM_Warning(prog, "VM_CL_getstats: index>MAX_CL_STATS-4 or index<0\n");
                return;
        }
-       dp_strlcpy(t, (char*)&cl.stats[i], sizeof(t));
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, t);
+       t_len = dp_strlcpy(t, (char*)&cl.stats[i], sizeof(t));
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, t, t_len);
 }
 
 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
@@ -2374,9 +2375,10 @@ static void VM_CL_runplayerphysics (prvm_prog_t *prog)
 //#348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
 static void VM_CL_getplayerkey (prvm_prog_t *prog)
 {
-       int                     i;
-       char            t[128];
-       const char      *c;
+       int i;
+       char t[128];
+       size_t t_len;
+       const char *c;
 
        VM_SAFEPARMCOUNT(2, VM_CL_getplayerkey);
 
@@ -2393,37 +2395,37 @@ static void VM_CL_getplayerkey (prvm_prog_t *prog)
        t[0] = 0;
 
        if(!strcasecmp(c, "name"))
-               dp_strlcpy(t, cl.scores[i].name, sizeof(t));
+               t_len = dp_strlcpy(t, cl.scores[i].name, sizeof(t));
        else
                if(!strcasecmp(c, "frags"))
-                       dpsnprintf(t, sizeof(t), "%i", cl.scores[i].frags);
+                       t_len = dpsnprintf(t, sizeof(t), "%i", cl.scores[i].frags);
        else
                if(!strcasecmp(c, "ping"))
-                       dpsnprintf(t, sizeof(t), "%i", cl.scores[i].qw_ping);
+                       t_len = dpsnprintf(t, sizeof(t), "%i", cl.scores[i].qw_ping);
        else
                if(!strcasecmp(c, "pl"))
-                       dpsnprintf(t, sizeof(t), "%i", cl.scores[i].qw_packetloss);
+                       t_len = dpsnprintf(t, sizeof(t), "%i", cl.scores[i].qw_packetloss);
        else
                if(!strcasecmp(c, "movementloss"))
-                       dpsnprintf(t, sizeof(t), "%i", cl.scores[i].qw_movementloss);
+                       t_len = dpsnprintf(t, sizeof(t), "%i", cl.scores[i].qw_movementloss);
        else
                if(!strcasecmp(c, "entertime"))
-                       dpsnprintf(t, sizeof(t), "%f", cl.scores[i].qw_entertime);
+                       t_len = dpsnprintf(t, sizeof(t), "%f", cl.scores[i].qw_entertime);
        else
                if(!strcasecmp(c, "colors"))
-                       dpsnprintf(t, sizeof(t), "%i", cl.scores[i].colors);
+                       t_len = dpsnprintf(t, sizeof(t), "%i", cl.scores[i].colors);
        else
                if(!strcasecmp(c, "topcolor"))
-                       dpsnprintf(t, sizeof(t), "%i", cl.scores[i].colors & 0xf0);
+                       t_len = dpsnprintf(t, sizeof(t), "%i", cl.scores[i].colors & 0xf0);
        else
                if(!strcasecmp(c, "bottomcolor"))
-                       dpsnprintf(t, sizeof(t), "%i", (cl.scores[i].colors &15)<<4);
+                       t_len = dpsnprintf(t, sizeof(t), "%i", (cl.scores[i].colors &15)<<4);
        else
                if(!strcasecmp(c, "viewentity"))
-                       dpsnprintf(t, sizeof(t), "%i", i+1);
+                       t_len = dpsnprintf(t, sizeof(t), "%i", i+1);
        if(!t[0])
                return;
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, t);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, t, t_len);
 }
 
 //#351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC)
@@ -2491,8 +2493,11 @@ static void VM_CL_ReadAngle (prvm_prog_t *prog)
 //#366 string() readstring (EXT_CSQC)
 static void VM_CL_ReadString (prvm_prog_t *prog)
 {
+       size_t cl_readstring_len;
+
        VM_SAFEPARMCOUNT(0, VM_CL_ReadString);
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)));
+       cl_readstring_len = MSG_ReadString_len(&cl_message, cl_readstring, sizeof(cl_readstring));
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, cl_readstring, cl_readstring_len);
 }
 
 //#367 float() readfloat (EXT_CSQC)
@@ -2507,6 +2512,7 @@ extern cvar_t cl_readpicture_force;
 static void VM_CL_ReadPicture (prvm_prog_t *prog)
 {
        const char *name;
+       size_t name_len;
        unsigned char *data;
        unsigned char *buf;
        unsigned short size;
@@ -2515,7 +2521,8 @@ static void VM_CL_ReadPicture (prvm_prog_t *prog)
 
        VM_SAFEPARMCOUNT(0, VM_CL_ReadPicture);
 
-       name = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring));
+       name_len = MSG_ReadString_len(&cl_message, cl_readstring, sizeof(cl_readstring));
+       name = cl_readstring;
        size = (unsigned short) MSG_ReadShort(&cl_message);
 
        // check if a texture of that name exists
@@ -2546,7 +2553,7 @@ static void VM_CL_ReadPicture (prvm_prog_t *prog)
                }
        }
 
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, name);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, name, name_len);
 }
 
 //////////////////////////////////////////////////////////
@@ -3409,7 +3416,7 @@ static void VM_CL_gettaginfo (prvm_prog_t *prog)
        Matrix4x4_ToVectors(&tag_localmatrix, forward, left, up, origin);
 
        PRVM_clientglobalfloat(gettaginfo_parent) = parentindex;
-       PRVM_clientglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
+       PRVM_clientglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname, strlen(tagname)) : 0;
        VectorCopy(forward, PRVM_clientglobalvector(gettaginfo_forward));
        VectorScale(left, -1, PRVM_clientglobalvector(gettaginfo_right));
        VectorCopy(up, PRVM_clientglobalvector(gettaginfo_up));
@@ -4496,7 +4503,7 @@ static void VM_CL_serverkey(prvm_prog_t *prog)
        char string[VM_TEMPSTRING_MAXSIZE];
        VM_SAFEPARMCOUNT(1, VM_CL_serverkey);
        InfoString_GetValue(cl.qw_serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string, strlen(string));
 }
 
 /*
@@ -4657,7 +4664,7 @@ static void VM_CL_skel_get_bonename(prvm_prog_t *prog)
                return;
        if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
                return;
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name, strlen(skeleton->model->data_bones[bonenum].name));
 }
 
 // #267 float(float skel, float bonenum) skel_get_boneparent = #267; // (FTE_CSQC_SKELETONOBJECTS) returns parent num for supplied bonenum, 0 if bonenum has no parent or bone does not exist (returned value is always less than bonenum, you can loop on this)
diff --git a/cmd.c b/cmd.c
index 667b9009b0d24f858574311f0e84a03a94ca1615..0dfc093d5bd9ea683062af2ec8c002451d4900c8 100644 (file)
--- a/cmd.c
+++ b/cmd.c
@@ -348,11 +348,12 @@ Cbuf_Execute
 ============
 */
 extern qbool prvm_runawaycheck;
-static qbool Cmd_PreprocessString(cmd_state_t *cmd, const char *intext, char *outtext, unsigned maxoutlen, cmd_alias_t *alias );
+static size_t Cmd_PreprocessString(cmd_state_t *cmd, const char *intext, char *outtext, unsigned maxoutlen, cmd_alias_t *alias);
 void Cbuf_Execute (cmd_buf_t *cbuf)
 {
        cmd_input_t *current;
        char preprocessed[MAX_INPUTLINE];
+       size_t preprocessed_len;
        char *firstchar;
        unsigned int i = 0;
 
@@ -380,16 +381,16 @@ void Cbuf_Execute (cmd_buf_t *cbuf)
                firstchar = current->text;
                while(*firstchar && ISWHITESPACE(*firstchar))
                        ++firstchar;
-               if((strncmp(firstchar, "alias", 5)   || !ISWHITESPACE(firstchar[5])) &&
-                  (strncmp(firstchar, "bind", 4)    || !ISWHITESPACE(firstchar[4])) &&
-                  (strncmp(firstchar, "in_bind", 7) || !ISWHITESPACE(firstchar[7])))
+               if((strncmp(firstchar, "alias", 5)   || !ISWHITESPACE(firstchar[5]))
+               && (strncmp(firstchar, "bind", 4)    || !ISWHITESPACE(firstchar[4]))
+               && (strncmp(firstchar, "in_bind", 7) || !ISWHITESPACE(firstchar[7])))
                {
-                       if(Cmd_PreprocessString(current->source, current->text, preprocessed, sizeof(preprocessed), NULL ))
-                               Cmd_ExecuteString(current->source, preprocessed, src_local, false);
+                       if((preprocessed_len = Cmd_PreprocessString(current->source, current->text, preprocessed, sizeof(preprocessed), NULL)))
+                               Cmd_ExecuteString(current->source, preprocessed, preprocessed_len, src_local, false);
                }
                else
                {
-                       Cmd_ExecuteString (current->source, current->text, src_local, false);
+                       Cmd_ExecuteString(current->source, current->text, current->length, src_local, false);
                }
 
                // Recycle memory so using WASD doesn't cause a malloc and free
@@ -1280,12 +1281,14 @@ static const char *Cmd_GetCvarValue(cmd_state_t *cmd, const char *var, size_t va
        return varstr;
 }
 
-/*
+/**
 Cmd_PreprocessString
 
 Preprocesses strings and replaces $*, $param#, $cvar accordingly. Also strips comments.
+Returns the number of bytes written to *outtext excluding the \0 terminator.
 */
-static qbool Cmd_PreprocessString(cmd_state_t *cmd, const char *intext, char *outtext, unsigned maxoutlen, cmd_alias_t *alias ) {
+static size_t Cmd_PreprocessString(cmd_state_t *cmd, const char *intext, char *outtext, unsigned maxoutlen, cmd_alias_t *alias)
+{
        const char *in;
        size_t eat, varlen;
        unsigned outlen;
@@ -1293,7 +1296,7 @@ static qbool Cmd_PreprocessString(cmd_state_t *cmd, const char *intext, char *ou
 
        // don't crash if there's no room in the outtext buffer
        if( maxoutlen == 0 ) {
-               return false;
+               return 0;
        }
        maxoutlen--; // because of \0
 
@@ -1366,7 +1369,7 @@ static qbool Cmd_PreprocessString(cmd_state_t *cmd, const char *intext, char *ou
                                {
                                        val = Cmd_GetCvarValue(cmd, in + 1, varlen, alias);
                                        if(!val)
-                                               return false;
+                                               return 0;
                                        eat = varlen + 2;
                                }
                                else
@@ -1379,7 +1382,7 @@ static qbool Cmd_PreprocessString(cmd_state_t *cmd, const char *intext, char *ou
                                varlen = strspn(in, "#*0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-");
                                val = Cmd_GetCvarValue(cmd, in, varlen, alias);
                                if(!val)
-                                       return false;
+                                       return 0;
                                eat = varlen;
                        }
                        if(val)
@@ -1403,8 +1406,8 @@ static qbool Cmd_PreprocessString(cmd_state_t *cmd, const char *intext, char *ou
                else 
                        outtext[outlen++] = *in++;
        }
-       outtext[outlen] = 0;
-       return true;
+       outtext[outlen] = '\0';
+       return outlen;
 }
 
 /*
@@ -2096,7 +2099,7 @@ extern cvar_t sv_cheats;
  * implement that behavior that doesn't involve an #ifdef, or
  * making a mess of hooks.
  */
-qbool Cmd_Callback(cmd_state_t *cmd, cmd_function_t *func, const char *text, cmd_source_t src)
+qbool Cmd_Callback(cmd_state_t *cmd, cmd_function_t *func)
 {
        if (func->function)
                func->function(cmd);
@@ -2105,13 +2108,13 @@ qbool Cmd_Callback(cmd_state_t *cmd, cmd_function_t *func, const char *text, cmd
        return true;
 }
 
-qbool Cmd_CL_Callback(cmd_state_t *cmd, cmd_function_t *func, const char *text, cmd_source_t src)
+qbool Cmd_CL_Callback(cmd_state_t *cmd, cmd_function_t *func, const char *text, size_t textlen, cmd_source_t src)
 {
        // TODO: Assign these functions to QC commands directly?
        if(func->qcfunc)
        {
-               if(((func->flags & CF_CLIENT) && CL_VM_ConsoleCommand(text)) ||
-                  ((func->flags & CF_SERVER) && SV_VM_ConsoleCommand(text)))
+               if(((func->flags & CF_CLIENT) && CL_VM_ConsoleCommand(text, textlen)) ||
+                  ((func->flags & CF_SERVER) && SV_VM_ConsoleCommand(text, textlen)))
                        return true;
 
                if (func->overridden) // If this QC command overrides an engine command,
@@ -2130,13 +2133,13 @@ qbool Cmd_CL_Callback(cmd_state_t *cmd, cmd_function_t *func, const char *text,
                        return true;
                }
        }
-       return Cmd_Callback(cmd, func, text, src);
+       return Cmd_Callback(cmd, func);
 }
 
-qbool Cmd_SV_Callback(cmd_state_t *cmd, cmd_function_t *func, const char *text, cmd_source_t src)
+qbool Cmd_SV_Callback(cmd_state_t *cmd, cmd_function_t *func, const char *text, size_t textlen, cmd_source_t src)
 {
        if(func->qcfunc && (func->flags & CF_SERVER))
-               return SV_VM_ConsoleCommand(text);
+               return SV_VM_ConsoleCommand(text, textlen);
        else if (src == src_client)
        {
                if((func->flags & CF_CHEAT) && !sv_cheats.integer)
@@ -2156,7 +2159,7 @@ A complete command line has been parsed, so try to execute it
 FIXME: lookupnoadd the token to speed search?
 ============
 */
-void Cmd_ExecuteString (cmd_state_t *cmd, const char *text, cmd_source_t src, qbool lockmutex)
+void Cmd_ExecuteString(cmd_state_t *cmd, const char *text, size_t textlen, cmd_source_t src, qbool lockmutex)
 {
        int oldpos;
        cmd_function_t *func;
@@ -2176,12 +2179,12 @@ void Cmd_ExecuteString (cmd_state_t *cmd, const char *text, cmd_source_t src, qb
 // check functions
        for (func = cmd->userdefined->qc_functions; func; func = func->next)
                if (!strcasecmp(cmd->argv[0], func->name))
-                       if(cmd->Handle(cmd, func, text, src))
+                       if(cmd->Handle(cmd, func, text, textlen, src))
                                goto functions_done;
 
        for (func = cmd->engine_functions; func; func=func->next)
                if (!strcasecmp (cmd->argv[0], func->name))
-                       if(cmd->Handle(cmd, func, text, src))
+                       if(cmd->Handle(cmd, func, text, textlen, src))
                                goto functions_done;
 
 functions_done:
diff --git a/cmd.h b/cmd.h
index 614aa0a094b725012e42037ba7ae3134f51144e3..cc912f31767adf280e4e180f882a7deab10422ca 100644 (file)
--- a/cmd.h
+++ b/cmd.h
@@ -143,13 +143,13 @@ typedef struct cmd_state_s
        unsigned cvars_flagsmask; // which CVAR_* flags should be visible to this interpreter? (CF_CLIENT | CF_SERVER, or just CF_SERVER)
        unsigned cmd_flagsmask; // cmd flags that identify this interpreter
 
-       qbool (*Handle)(struct cmd_state_s *, struct cmd_function_s *, const char *, enum cmd_source_s);
+       qbool (*Handle)(struct cmd_state_s *, struct cmd_function_s *, const char *, size_t, enum cmd_source_s);
 }
 cmd_state_t;
 
-qbool Cmd_Callback(cmd_state_t *cmd, cmd_function_t *func, const char *text, cmd_source_t src);
-qbool Cmd_CL_Callback(cmd_state_t *cmd, cmd_function_t *func, const char *text, cmd_source_t src);
-qbool Cmd_SV_Callback(cmd_state_t *cmd, cmd_function_t *func, const char *text, cmd_source_t src);
+qbool Cmd_Callback(cmd_state_t *cmd, cmd_function_t *func);
+qbool Cmd_CL_Callback(cmd_state_t *cmd, cmd_function_t *func, const char *text, size_t textlen, cmd_source_t src);
+qbool Cmd_SV_Callback(cmd_state_t *cmd, cmd_function_t *func, const char *text, size_t textlen, cmd_source_t src);
 
 typedef struct cmd_input_s
 {
@@ -267,7 +267,7 @@ int Cmd_CheckParm (cmd_state_t *cmd, const char *parm);
 
 /// Parses a single line of text into arguments and tries to execute it.
 /// The text can come from the command buffer, a remote client, or stdin.
-void Cmd_ExecuteString (cmd_state_t *cmd, const char *text, cmd_source_t src, qbool lockmutex);
+void Cmd_ExecuteString(cmd_state_t *cmd, const char *text, size_t textlen, cmd_source_t src, qbool lockmutex);
 
 /// quotes a string so that it can be used as a command argument again;
 /// quoteset is a string that contains one or more of ", \, $ and specifies
index 80503b62b5307ff3d1ebf44ebf94da2aa02144e4..fe29579ed07c3acc78f4a8fa8e537440b1492935 100644 (file)
--- a/com_msg.c
+++ b/com_msg.c
@@ -346,9 +346,20 @@ char *MSG_ReadString (sizebuf_t *sb, char *string, size_t maxstring)
        while ((c = MSG_ReadByte(sb)) > 0)
                if (l < maxstring - 1)
                        string[l++] = c;
-       string[l] = 0;
+       string[l] = '\0';
        return string;
 }
+size_t MSG_ReadString_len (sizebuf_t *sb, char *string, size_t maxstring)
+{
+       int c;
+       size_t l = 0;
+       // read string into sbfer, but only store as many characters as will fit
+       while ((c = MSG_ReadByte(sb)) > 0)
+               if (l < maxstring - 1)
+                       string[l++] = c;
+       string[l] = '\0';
+       return l;
+}
 
 int MSG_ReadBytes (sizebuf_t *sb, int numbytes, unsigned char *out)
 {
index 05bbd7c64086a6aa4b31d5203973c53449f782ed..0f0572d35302d890d7a80bae6ec1e1c312a7c7df 100644 (file)
--- a/common.c
+++ b/common.c
@@ -37,6 +37,7 @@ cvar_t cl_playermodel = {CF_CLIENT | CF_SERVER | CF_USERINFO | CF_ARCHIVE, "play
 cvar_t cl_playerskin = {CF_CLIENT | CF_SERVER | CF_USERINFO | CF_ARCHIVE, "playerskin", "", "current player skin in Nexuiz/Xonotic"};
 
 char com_token[MAX_INPUTLINE];
+unsigned com_token_len;
 
 //===========================================================================
 
@@ -456,6 +457,7 @@ int COM_Wordwrap(const char *string, size_t length, float continuationWidth, flo
 COM_ParseToken_Simple
 
 Parse a token out of a string
+Writes the token and its strlen to the com_token and com_token_len globals.
 ==============
 */
 int COM_ParseToken_Simple(const char **datapointer, qbool returnnewline, qbool parsebackslash, qbool parsecomments)
@@ -464,8 +466,8 @@ int COM_ParseToken_Simple(const char **datapointer, qbool returnnewline, qbool p
        int c;
        const char *data = *datapointer;
 
-       len = 0;
-       com_token[0] = 0;
+       com_token_len = len = 0;
+       com_token[0] = '\0';
 
        if (!data)
        {
@@ -530,7 +532,8 @@ skipwhite:
                        if (len < (int)sizeof(com_token) - 1)
                                com_token[len++] = c;
                }
-               com_token[len] = 0;
+               com_token[len] = '\0';
+               com_token_len = len;
                if (*data == '\"')
                        data++;
                *datapointer = data;
@@ -540,7 +543,8 @@ skipwhite:
        {
                // translate Mac line ending to UNIX
                com_token[len++] = '\n';data++;
-               com_token[len] = 0;
+               com_token[len] = '\0';
+               com_token_len = len;
                *datapointer = data;
                return true;
        }
@@ -548,7 +552,8 @@ skipwhite:
        {
                // single character
                com_token[len++] = *data++;
-               com_token[len] = 0;
+               com_token[len] = '\0';
+               com_token_len = len;
                *datapointer = data;
                return true;
        }
@@ -558,7 +563,8 @@ skipwhite:
                for (;!ISWHITESPACE(*data);data++)
                        if (len < (int)sizeof(com_token) - 1)
                                com_token[len++] = *data;
-               com_token[len] = 0;
+               com_token[len] = '\0';
+               com_token_len = len;
                *datapointer = data;
                return true;
        }
@@ -569,6 +575,7 @@ skipwhite:
 COM_ParseToken_QuakeC
 
 Parse a token out of a string
+Writes the token and its strlen to the com_token and com_token_len globals.
 ==============
 */
 int COM_ParseToken_QuakeC(const char **datapointer, qbool returnnewline)
@@ -577,8 +584,8 @@ int COM_ParseToken_QuakeC(const char **datapointer, qbool returnnewline)
        int c;
        const char *data = *datapointer;
 
-       len = 0;
-       com_token[0] = 0;
+       com_token_len = len = 0;
+       com_token[0] = '\0';
 
        if (!data)
        {
@@ -644,7 +651,8 @@ skipwhite:
                        if (len < (int)sizeof(com_token) - 1)
                                com_token[len++] = c;
                }
-               com_token[len] = 0;
+               com_token[len] = '\0';
+               com_token_len = len;
                if (*data == quote)
                        data++;
                *datapointer = data;
@@ -654,7 +662,8 @@ skipwhite:
        {
                // translate Mac line ending to UNIX
                com_token[len++] = '\n';data++;
-               com_token[len] = 0;
+               com_token[len] = '\0';
+               com_token_len = len;
                *datapointer = data;
                return true;
        }
@@ -662,7 +671,8 @@ skipwhite:
        {
                // single character
                com_token[len++] = *data++;
-               com_token[len] = 0;
+               com_token[len] = '\0';
+               com_token_len = len;
                *datapointer = data;
                return true;
        }
@@ -672,7 +682,8 @@ skipwhite:
                for (;!ISWHITESPACE(*data) && *data != '{' && *data != '}' && *data != ')' && *data != '(' && *data != ']' && *data != '[' && *data != ':' && *data != ',' && *data != ';';data++)
                        if (len < (int)sizeof(com_token) - 1)
                                com_token[len++] = *data;
-               com_token[len] = 0;
+               com_token[len] = '\0';
+               com_token_len = len;
                *datapointer = data;
                return true;
        }
@@ -683,6 +694,7 @@ skipwhite:
 COM_ParseToken_VM_Tokenize
 
 Parse a token out of a string
+Writes the token and its strlen to the com_token and com_token_len globals.
 ==============
 */
 int COM_ParseToken_VM_Tokenize(const char **datapointer, qbool returnnewline)
@@ -691,8 +703,8 @@ int COM_ParseToken_VM_Tokenize(const char **datapointer, qbool returnnewline)
        int c;
        const char *data = *datapointer;
 
-       len = 0;
-       com_token[0] = 0;
+       com_token_len = len = 0;
+       com_token[0] = '\0';
 
        if (!data)
        {
@@ -758,7 +770,8 @@ skipwhite:
                        if (len < (int)sizeof(com_token) - 1)
                                com_token[len++] = c;
                }
-               com_token[len] = 0;
+               com_token[len] = '\0';
+               com_token_len = len;
                if (*data == quote)
                        data++;
                *datapointer = data;
@@ -768,7 +781,8 @@ skipwhite:
        {
                // translate Mac line ending to UNIX
                com_token[len++] = '\n';data++;
-               com_token[len] = 0;
+               com_token[len] = '\0';
+               com_token_len = len;
                *datapointer = data;
                return true;
        }
@@ -776,7 +790,8 @@ skipwhite:
        {
                // single character
                com_token[len++] = *data++;
-               com_token[len] = 0;
+               com_token[len] = '\0';
+               com_token_len = len;
                *datapointer = data;
                return true;
        }
@@ -786,7 +801,8 @@ skipwhite:
                for (;!ISWHITESPACE(*data) && *data != '{' && *data != '}' && *data != ')' && *data != '(' && *data != ']' && *data != '[' && *data != ':' && *data != ',' && *data != ';';data++)
                        if (len < (int)sizeof(com_token) - 1)
                                com_token[len++] = *data;
-               com_token[len] = 0;
+               com_token[len] = '\0';
+               com_token_len = len;
                *datapointer = data;
                return true;
        }
@@ -797,6 +813,7 @@ skipwhite:
 COM_ParseToken_Console
 
 Parse a token out of a string, behaving like the qwcl console
+Writes the token and its strlen to the com_token and com_token_len globals.
 ==============
 */
 int COM_ParseToken_Console(const char **datapointer)
@@ -804,8 +821,8 @@ int COM_ParseToken_Console(const char **datapointer)
        int len;
        const char *data = *datapointer;
 
-       len = 0;
-       com_token[0] = 0;
+       com_token_len = len = 0;
+       com_token[0] = '\0';
 
        if (!data)
        {
@@ -843,7 +860,8 @@ skipwhite:
                        if (len < (int)sizeof(com_token) - 1)
                                com_token[len++] = *data;
                }
-               com_token[len] = 0;
+               com_token[len] = '\0';
+               com_token_len = len;
                if (*data == '\"')
                        data++;
                *datapointer = data;
@@ -854,7 +872,8 @@ skipwhite:
                for (;!ISWHITESPACE(*data);data++)
                        if (len < (int)sizeof(com_token) - 1)
                                com_token[len++] = *data;
-               com_token[len] = 0;
+               com_token[len] = '\0';
+               com_token_len = len;
                *datapointer = data;
        }
 
@@ -1014,10 +1033,12 @@ int dpvsnprintf (char *buffer, size_t buffersize, const char *format, va_list ar
 
 //======================================
 
-void COM_ToLowerString (const char *in, char *out, size_t size_out)
+size_t COM_ToLowerString(const char *in, char *out, size_t size_out)
 {
+       const char *out_start = out;
+
        if (size_out == 0)
-               return;
+               return 0;
 
        if(utf8_enable.integer)
        {
@@ -1028,12 +1049,12 @@ void COM_ToLowerString (const char *in, char *out, size_t size_out)
                        Uchar ch = u8_getchar_utf8_enabled(in, &in);
                        ch = u8_tolower(ch);
                        n = u8_fromchar(ch, out, size_out);
+                       out += n; // before the break so the return is correct
                        if(n <= 0)
                                break;
-                       out += n;
                        size_out -= n;
                }
-               return;
+               return out - out_start;
        }
 
        while (*in && size_out > 1)
@@ -1045,12 +1066,15 @@ void COM_ToLowerString (const char *in, char *out, size_t size_out)
                size_out--;
        }
        *out = '\0';
+       return out - out_start;
 }
 
-void COM_ToUpperString (const char *in, char *out, size_t size_out)
+size_t COM_ToUpperString(const char *in, char *out, size_t size_out)
 {
+       const char *out_start = out;
+
        if (size_out == 0)
-               return;
+               return 0;
 
        if(utf8_enable.integer)
        {
@@ -1061,12 +1085,12 @@ void COM_ToUpperString (const char *in, char *out, size_t size_out)
                        Uchar ch = u8_getchar_utf8_enabled(in, &in);
                        ch = u8_toupper(ch);
                        n = u8_fromchar(ch, out, size_out);
+                       out += n; // before the break so the return is correct
                        if(n <= 0)
                                break;
-                       out += n;
                        size_out -= n;
                }
-               return;
+               return out - out_start;
        }
 
        while (*in && size_out > 1)
@@ -1078,6 +1102,7 @@ void COM_ToUpperString (const char *in, char *out, size_t size_out)
                size_out--;
        }
        *out = '\0';
+       return out - out_start;
 }
 
 int COM_StringBeginsWith(const char *s, const char *match)
@@ -1231,9 +1256,10 @@ removes color codes from a string.
 If escape_carets is true, the resulting string will be safe for printing. If
 escape_carets is false, the function will just strip color codes (for logging
 for example).
+Returns the number of bytes written to the *out buffer excluding the \0 terminator.
 
-If the output buffer size did not suffice for converting, the function returns
-FALSE. Generally, if escape_carets is false, the output buffer needs
+If the output buffer size did not suffice for converting, the function returns 0.
+Generally, if escape_carets is false, the output buffer needs
 strlen(str)+1 bytes, and if escape_carets is true, it can need strlen(str)*1.5+2
 bytes. In any case, the function makes sure that the resulting string is
 zero terminated.
@@ -1242,20 +1268,22 @@ For size_in, specify the maximum number of characters from in to use, or 0 to us
 all characters until the zero terminator.
 ============
 */
-qbool
-COM_StringDecolorize(const char *in, size_t size_in, char *out, size_t size_out, qbool escape_carets)
+size_t COM_StringDecolorize(const char *in, size_t size_in, char *out, size_t size_out, qbool escape_carets)
 {
-#define APPEND(ch) do { if(--size_out) { *out++ = (ch); } else { *out++ = 0; return false; } } while(0)
+#define APPEND(ch) do { if(--size_out) { *out++ = (ch); } else { *out++ = 0; return 0; } } while(0)
+
+       const char *out_start = out;
        const char *end = size_in ? (in + size_in) : NULL;
+
        if(size_out < 1)
-               return false;
+               return 0;
        for(;;)
        {
                switch((in == end) ? 0 : *in)
                {
                        case 0:
-                               *out++ = 0;
-                               return true;
+                               *out = '\0';
+                               return out - out_start;
                        case STRING_COLOR_TAG:
                                ++in;
                                switch((in == end) ? 0 : *in)
@@ -1278,8 +1306,8 @@ COM_StringDecolorize(const char *in, size_t size_in, char *out, size_t size_out,
                                                // finish the code by appending another caret when escaping
                                                if(escape_carets)
                                                        APPEND(STRING_COLOR_TAG);
-                                               *out++ = 0;
-                                               return true;
+                                               *out = '\0';
+                                               return out - out_start;
                                        case STRING_COLOR_TAG: // escaped ^
                                                APPEND(STRING_COLOR_TAG);
                                                // append a ^ twice when escaping
index ff088a790546d420c6205236329cfcfec2ef7873..e85f43eb9ebd9dca8fc5631adacbe15d41d9f753 100644 (file)
--- a/common.h
+++ b/common.h
@@ -180,6 +180,8 @@ int MSG_ReadBigLong (sizebuf_t *sb);
 float MSG_ReadLittleFloat (sizebuf_t *sb);
 float MSG_ReadBigFloat (sizebuf_t *sb);
 char *MSG_ReadString (sizebuf_t *sb, char *string, size_t maxstring);
+/// Same as MSG_ReadString except it returns the number of bytes written to *string excluding the \0 terminator.
+size_t MSG_ReadString_len (sizebuf_t *sb, char *string, size_t maxstring);
 int MSG_ReadBytes (sizebuf_t *sb, int numbytes, unsigned char *out);
 
 #define MSG_ReadChar(sb) ((sb)->readcount >= (sb)->cursize ? ((sb)->badread = true, -1) : (signed char)(sb)->data[(sb)->readcount++])
@@ -205,7 +207,7 @@ typedef int (*COM_LineProcessorFunc) (void *passthrough, const char *line, size_
 int COM_Wordwrap(const char *string, size_t length, float continuationSize, float maxWidth, COM_WordWidthFunc_t wordWidth, void *passthroughCW, COM_LineProcessorFunc processLine, void *passthroughPL);
 
 extern char com_token[MAX_INPUTLINE];
-
+extern unsigned com_token_len;
 int COM_ParseToken_Simple(const char **datapointer, qbool returnnewline, qbool parsebackslash, qbool parsecomments);
 int COM_ParseToken_QuakeC(const char **datapointer, qbool returnnewline);
 int COM_ParseToken_VM_Tokenize(const char **datapointer, qbool returnnewline);
@@ -277,16 +279,15 @@ typedef enum userdirmode_e
 }
 userdirmode_t;
 
-void COM_ToLowerString (const char *in, char *out, size_t size_out);
-void COM_ToUpperString (const char *in, char *out, size_t size_out);
+/// Returns the number of bytes written to *out excluding the \0 terminator.
+size_t COM_ToLowerString(const char *in, char *out, size_t size_out);
+/// Returns the number of bytes written to *out excluding the \0 terminator.
+size_t COM_ToUpperString(const char *in, char *out, size_t size_out);
 int COM_StringBeginsWith(const char *s, const char *match);
-
 int COM_ReadAndTokenizeLine(const char **text, char **argv, int maxargc, char *tokenbuf, int tokenbufsize, const char *commentprefix);
-
 size_t COM_StringLengthNoColors(const char *s, size_t size_s, qbool *valid);
-qbool COM_StringDecolorize(const char *in, size_t size_in, char *out, size_t size_out, qbool escape_carets);
-void COM_ToLowerString (const char *in, char *out, size_t size_out);
-void COM_ToUpperString (const char *in, char *out, size_t size_out);
+size_t COM_StringDecolorize(const char *in, size_t size_in, char *out, size_t size_out, qbool escape_carets);
+
 
 
 #define dp_strlcpy(dst, src, dsize) dp__strlcpy(dst, src, dsize, __func__, __LINE__)
index eefcb25e975b8c0a8f4de738ba07199c59dc6cde..99414a215cf5737dba10ace9c5ef791175063600 100644 (file)
--- a/console.c
+++ b/console.c
@@ -719,8 +719,9 @@ static void Con_MsgCmdMode(cmd_state_t *cmd, signed char mode)
        chat_mode = mode;
        if(Cmd_Argc(cmd) > 1)
        {
-               dpsnprintf(chat_buffer, sizeof(chat_buffer), "%s ", Cmd_Args(cmd));
-               chat_bufferpos = (unsigned int)strlen(chat_buffer);
+               chat_bufferpos = dpsnprintf(chat_buffer, sizeof(chat_buffer), "%s ", Cmd_Args(cmd));
+               if (chat_bufferpos < 0)
+                       chat_bufferpos = 0;
        }
 }
 
index f7e6fd004197831b5c3f376884d3a265ed1e429b..c060ee14f4544729ea7434db7141acba4cbde7e3 100644 (file)
--- a/csprogs.c
+++ b/csprogs.c
@@ -529,10 +529,10 @@ qbool CL_VM_UpdateView (double frametime)
        return true;
 }
 
-qbool CL_VM_ConsoleCommand (const char *text)
+qbool CL_VM_ConsoleCommand(const char *text, size_t textlen)
 {
        prvm_prog_t *prog = CLVM_prog;
-       return PRVM_ConsoleCommand(prog, text, &prog->funcoffsets.CSQC_ConsoleCommand, false, cl.csqc_server2csqcentitynumber[cl.playerentity], cl.time, cl.csqc_loaded, "QC function CSQC_ConsoleCommand is missing");
+       return PRVM_ConsoleCommand(prog, text, textlen, &prog->funcoffsets.CSQC_ConsoleCommand, false, cl.csqc_server2csqcentitynumber[cl.playerentity], cl.time, cl.csqc_loaded, "QC function CSQC_ConsoleCommand is missing");
 }
 
 qbool CL_VM_Parse_TempEntity (void)
@@ -560,7 +560,7 @@ qbool CL_VM_Parse_TempEntity (void)
        return r;
 }
 
-void CL_VM_Parse_StuffCmd (const char *msg)
+void CL_VM_Parse_StuffCmd(const char *msg, size_t msg_len)
 {
        prvm_prog_t *prog = CLVM_prog;
        int restorevm_tempstringsbuf_cursize;
@@ -575,7 +575,7 @@ void CL_VM_Parse_StuffCmd (const char *msg)
                int crcflags = csqc_progcrc.flags;
                csqc_progcrc.flags &= ~CF_READONLY;
                csqc_progsize.flags &= ~CF_READONLY;
-               Cmd_ExecuteString(cmd_local, msg, src_local, true);
+               Cmd_ExecuteString(cmd_local, msg, msg_len, src_local, true);
                csqc_progcrc.flags = csqc_progsize.flags = crcflags;
                return;
        }
@@ -591,7 +591,7 @@ void CL_VM_Parse_StuffCmd (const char *msg)
                PRVM_clientglobalfloat(time) = cl.time;
                PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[cl.playerentity];
                restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize;
-               PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(prog, msg);
+               PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(prog, msg, msg_len);
                prog->ExecuteProgram(prog, PRVM_clientfunction(CSQC_Parse_StuffCmd), "QC function CSQC_Parse_StuffCmd is missing");
                prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
        }
@@ -600,48 +600,54 @@ void CL_VM_Parse_StuffCmd (const char *msg)
        CSQC_END
 }
 
-static void CL_VM_Parse_Print (const char *msg)
+static void CL_VM_Parse_Print(const char *msg, size_t msg_len)
 {
        prvm_prog_t *prog = CLVM_prog;
        int restorevm_tempstringsbuf_cursize;
        PRVM_clientglobalfloat(time) = cl.time;
        PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[cl.playerentity];
        restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize;
-       PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(prog, msg);
+       PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(prog, msg, msg_len);
        prog->ExecuteProgram(prog, PRVM_clientfunction(CSQC_Parse_Print), "QC function CSQC_Parse_Print is missing");
        prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
 }
 
-void CSQC_AddPrintText (const char *msg)
+void CSQC_AddPrintText(const char *msg, size_t msg_len)
 {
        prvm_prog_t *prog = CLVM_prog;
-       size_t i;
+       char *start = cl.csqc_printtextbuf + cl.csqc_printtextbuf_len;
+       size_t writebytes = min(msg_len + 1, MAX_INPUTLINE - cl.csqc_printtextbuf_len);
+
        CSQC_BEGIN
        if(cl.csqc_loaded && PRVM_clientfunction(CSQC_Parse_Print))
        {
-               // FIXME: is this bugged?
-               i = strlen(msg)-1;
-               if(msg[i] != '\n' && msg[i] != '\r')
+               if(msg[msg_len - 1] != '\n' && msg[msg_len - 1] != '\r')
                {
-                       if(strlen(cl.csqc_printtextbuf)+i >= MAX_INPUTLINE)
+                       if(cl.csqc_printtextbuf_len + msg_len + 1 >= MAX_INPUTLINE)
                        {
-                               CL_VM_Parse_Print(cl.csqc_printtextbuf);
-                               cl.csqc_printtextbuf[0] = 0;
+                               CL_VM_Parse_Print(cl.csqc_printtextbuf, cl.csqc_printtextbuf_len);
+                               cl.csqc_printtextbuf[0] = '\0';
+                               cl.csqc_printtextbuf_len = 0;
                        }
                        else
-                               dp_strlcat(cl.csqc_printtextbuf, msg, MAX_INPUTLINE);
+                       {
+                               memcpy(start, msg, writebytes);
+                               cl.csqc_printtextbuf_len += msg_len;
+                       }
                        return;
                }
-               dp_strlcat(cl.csqc_printtextbuf, msg, MAX_INPUTLINE);
-               CL_VM_Parse_Print(cl.csqc_printtextbuf);
-               cl.csqc_printtextbuf[0] = 0;
+               memcpy(start, msg, writebytes);
+               cl.csqc_printtextbuf_len += msg_len;
+               CL_VM_Parse_Print(cl.csqc_printtextbuf, cl.csqc_printtextbuf_len);
+               cl.csqc_printtextbuf[0] = '\0';
+               cl.csqc_printtextbuf_len = 0;
        }
        else
                Con_Print(msg);
        CSQC_END
 }
 
-void CL_VM_Parse_CenterPrint (const char *msg)
+void CL_VM_Parse_CenterPrint(const char *msg, size_t msg_len)
 {
        prvm_prog_t *prog = CLVM_prog;
        int restorevm_tempstringsbuf_cursize;
@@ -651,7 +657,7 @@ void CL_VM_Parse_CenterPrint (const char *msg)
                PRVM_clientglobalfloat(time) = cl.time;
                PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[cl.playerentity];
                restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize;
-               PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(prog, msg);
+               PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(prog, msg, msg_len);
                prog->ExecuteProgram(prog, PRVM_clientfunction(CSQC_Parse_CenterPrint), "QC function CSQC_Parse_CenterPrint is missing");
                prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
        }
@@ -693,7 +699,7 @@ qbool CL_VM_Event_Sound(int sound_num, float fvolume, int channel, float attenua
                        PRVM_clientglobaledict(self) = cl.csqc_server2csqcentitynumber[cl.playerentity];
                        PRVM_G_FLOAT(OFS_PARM0) = ent;
                        PRVM_G_FLOAT(OFS_PARM1) = CHAN_ENGINE2USER(channel);
-                       PRVM_G_INT(OFS_PARM2) = PRVM_SetTempString(prog, cl.sound_name[sound_num] );
+                       PRVM_G_INT(OFS_PARM2) = PRVM_SetTempString(prog, cl.sound_name[sound_num], strlen(cl.sound_name[sound_num]));
                        PRVM_G_FLOAT(OFS_PARM3) = fvolume;
                        PRVM_G_FLOAT(OFS_PARM4) = attenuation;
                        VectorCopy(pos, PRVM_G_VECTOR(OFS_PARM5) );
index 4760a7f3c68b5caae93f5840e2268cb4a81eb3c6..1900f91c3711c82805bf65fcabab4cc8cef4c5bc 100644 (file)
--- a/csprogs.h
+++ b/csprogs.h
@@ -111,20 +111,20 @@ void CL_VM_ShutDown(void);
 void CL_VM_UpdateIntermissionState(int intermission);
 void CL_VM_UpdateShowingScoresState(int showingscores);
 qbool CL_VM_InputEvent(int eventtype, float x, float y);
-qbool CL_VM_ConsoleCommand(const char *text);
+qbool CL_VM_ConsoleCommand(const char *text, size_t textlen);
 void CL_VM_UpdateDmgGlobals(int dmg_take, int dmg_save, vec3_t dmg_origin);
 void CL_VM_UpdateIntermissionState(int intermission);
 qbool CL_VM_Event_Sound(int sound_num, float volume, int channel, float attenuation, int ent, vec3_t pos, int flags, float speed);
 qbool CL_VM_Parse_TempEntity(void);
-void CL_VM_Parse_StuffCmd(const char *msg);
-void CL_VM_Parse_CenterPrint(const char *msg);
+void CL_VM_Parse_StuffCmd(const char *msg, size_t msg_len);
+void CL_VM_Parse_CenterPrint(const char *msg, size_t msg_len);
 int CL_GetPitchSign(prvm_prog_t *prog, prvm_edict_t *ent);
 int CL_GetTagMatrix(prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex, prvm_vec_t *shadingorigin);
 void CL_GetEntityMatrix(prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qbool viewmatrix);
 void QW_CL_StartUpload(unsigned char *data, int size);
 
 void CSQC_UpdateNetworkTimes(double newtime, double oldtime);
-void CSQC_AddPrintText(const char *msg);
+void CSQC_AddPrintText(const char *msg, size_t msg_len);
 void CSQC_ReadEntities(void);
 void CSQC_RelinkAllEntities(int drawmask);
 void CSQC_RelinkCSQCEntities(void);
diff --git a/keys.c b/keys.c
index 739d26bb050f2fe7d8f071a59a8da75667c13aac..a3a6d9268601045bd102472293893308021bc966 100644 (file)
--- a/keys.c
+++ b/keys.c
@@ -1308,7 +1308,7 @@ Key_Message (cmd_state_t *cmd, int key, int ascii)
        if (key == K_ENTER || key == K_KP_ENTER || ascii == 10 || ascii == 13)
        {
                if(chat_mode < 0)
-                       Cmd_ExecuteString(cmd, chat_buffer, src_local, true); // not Cbuf_AddText to allow semiclons in args; however, this allows no variables then. Use aliases!
+                       Cmd_ExecuteString(cmd, chat_buffer, strlen(chat_buffer), src_local, true); // not Cbuf_AddText to allow semiclons in args; however, this allows no variables then. Use aliases!
                else
                        CL_ForwardToServer(va(vabuf, sizeof(vabuf), "%s %s", chat_mode ? "say_team" : "say ", chat_buffer));
 
diff --git a/lhnet.c b/lhnet.c
index 05fd9802a971edc6daa1ad4840291ef3e0f279b9..e6a688de7c3fd67c4ee7108597da998dc947f284 100644 (file)
--- a/lhnet.c
+++ b/lhnet.c
@@ -553,8 +553,7 @@ int LHNETADDRESS_ToString(const lhnetaddress_t *vaddress, char *string, int stri
                {
                        if (stringbuffersize >= 12)
                        {
-                               dpsnprintf(string, stringbuffersize, "local:%d", address->port);
-                               return 1;
+                               return dpsnprintf(string, stringbuffersize, "local:%d", address->port);
                        }
                }
                else
@@ -562,7 +561,7 @@ int LHNETADDRESS_ToString(const lhnetaddress_t *vaddress, char *string, int stri
                        if (stringbuffersize >= 6)
                        {
                                memcpy(string, "local", 6);
-                               return 1;
+                               return 5;
                        }
                }
                break;
@@ -572,16 +571,14 @@ int LHNETADDRESS_ToString(const lhnetaddress_t *vaddress, char *string, int stri
                {
                        if (stringbuffersize >= 22)
                        {
-                               dpsnprintf(string, stringbuffersize, "%d.%d.%d.%d:%d", a[0], a[1], a[2], a[3], address->port);
-                               return 1;
+                               return dpsnprintf(string, stringbuffersize, "%d.%d.%d.%d:%d", a[0], a[1], a[2], a[3], address->port);
                        }
                }
                else
                {
                        if (stringbuffersize >= 16)
                        {
-                               dpsnprintf(string, stringbuffersize, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
-                               return 1;
+                               return dpsnprintf(string, stringbuffersize, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
                        }
                }
                break;
@@ -592,16 +589,14 @@ int LHNETADDRESS_ToString(const lhnetaddress_t *vaddress, char *string, int stri
                {
                        if (stringbuffersize >= 88)
                        {
-                               dpsnprintf(string, stringbuffersize, "[%x:%x:%x:%x:%x:%x:%x:%x]:%d", a[0] * 256 + a[1], a[2] * 256 + a[3], a[4] * 256 + a[5], a[6] * 256 + a[7], a[8] * 256 + a[9], a[10] * 256 + a[11], a[12] * 256 + a[13], a[14] * 256 + a[15], address->port);
-                               return 1;
+                               return dpsnprintf(string, stringbuffersize, "[%x:%x:%x:%x:%x:%x:%x:%x]:%d", a[0] * 256 + a[1], a[2] * 256 + a[3], a[4] * 256 + a[5], a[6] * 256 + a[7], a[8] * 256 + a[9], a[10] * 256 + a[11], a[12] * 256 + a[13], a[14] * 256 + a[15], address->port);
                        }
                }
                else
                {
                        if (stringbuffersize >= 80)
                        {
-                               dpsnprintf(string, stringbuffersize, "%x:%x:%x:%x:%x:%x:%x:%x", a[0] * 256 + a[1], a[2] * 256 + a[3], a[4] * 256 + a[5], a[6] * 256 + a[7], a[8] * 256 + a[9], a[10] * 256 + a[11], a[12] * 256 + a[13], a[14] * 256 + a[15]);
-                               return 1;
+                               return dpsnprintf(string, stringbuffersize, "%x:%x:%x:%x:%x:%x:%x:%x", a[0] * 256 + a[1], a[2] * 256 + a[3], a[4] * 256 + a[5], a[6] * 256 + a[7], a[8] * 256 + a[9], a[10] * 256 + a[11], a[12] * 256 + a[13], a[14] * 256 + a[15]);
                        }
                }
                break;
diff --git a/lhnet.h b/lhnet.h
index e7ac0e48294dc79878e01b17c5f2bb16b48552b7..d368940dbf2a04d79eb2243a4f18acda48f8cbce 100644 (file)
--- a/lhnet.h
+++ b/lhnet.h
@@ -26,6 +26,7 @@ lhnetaddress_t;
 
 int LHNETADDRESS_FromPort(lhnetaddress_t *address, lhnetaddresstype_t addresstype, int port);
 int LHNETADDRESS_FromString(lhnetaddress_t *address, const char *string, int defaultport);
+/// Returns the number of bytes written to *string excluding the \0 terminator.
 int LHNETADDRESS_ToString(const lhnetaddress_t *address, char *string, int stringbuffersize, int includeport);
 static inline lhnetaddresstype_t LHNETADDRESS_GetAddressType(const lhnetaddress_t *address)
 {
diff --git a/menu.h b/menu.h
index 6dd0b37c38dfac1c0a7681790f7fd7701fe133fd..2344f44434da5b0338e787db258f8b9d7a297ab7 100644 (file)
--- a/menu.h
+++ b/menu.h
@@ -71,7 +71,7 @@ void MP_Draw (void);
 void MP_ToggleMenu (int mode);
 void MP_Shutdown (void);*/
 
-qbool MP_ConsoleCommand(const char *text);
+qbool MP_ConsoleCommand(const char *text, size_t textlen);
 
 //
 // menu router
index 218b0c8de2b08a909ad3b72c0fc1f78ee5d4b163..ba785d59c239c824b953932f3f0d58d8b988959a 100644 (file)
@@ -53,10 +53,10 @@ const char *vm_m_extensions[] = {
 NULL
 };
 
-qbool MP_ConsoleCommand(const char *text)
+qbool MP_ConsoleCommand(const char *text, size_t textlen)
 {
        prvm_prog_t *prog = MVM_prog;
-       return PRVM_ConsoleCommand(prog, text, &prog->funcoffsets.GameCommand, false, -1, 0, prog->loaded, "QC function GameCommand is missing");
+       return PRVM_ConsoleCommand(prog, text, textlen, &prog->funcoffsets.GameCommand, false, -1, 0, prog->loaded, "QC function GameCommand is missing");
 }
 
 /*
@@ -220,9 +220,9 @@ static void VM_M_getgamedirinfo(prvm_prog_t *prog)
        if(nr >= 0 && nr < fs_all_gamedirs_count)
        {
                if(item == 0)
-                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( prog, fs_all_gamedirs[nr].name );
+                       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, fs_all_gamedirs[nr].name, strlen(fs_all_gamedirs[nr].name));
                else if(item == 1)
-                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( prog, fs_all_gamedirs[nr].description );
+                       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, fs_all_gamedirs[nr].description, strlen(fs_all_gamedirs[nr].description));
        }
 }
 
@@ -331,25 +331,25 @@ static void VM_M_setserverlistmaskstring(prvm_prog_t *prog)
 
        switch( field ) {
                case SLIF_CNAME:
-                       dp_strlcpy( mask->info.cname, str, sizeof(mask->info.cname) );
+                       mask->info.cname_len = dp_strlcpy(mask->info.cname, str, sizeof(mask->info.cname));
                        break;
                case SLIF_NAME:
-                       dp_strlcpy( mask->info.name, str, sizeof(mask->info.name)  );
+                       mask->info.name_len = dp_strlcpy(mask->info.name, str, sizeof(mask->info.name));
                        break;
                case SLIF_QCSTATUS:
-                       dp_strlcpy( mask->info.qcstatus, str, sizeof(mask->info.qcstatus)  );
+                       mask->info.qcstatus_len = dp_strlcpy(mask->info.qcstatus, str, sizeof(mask->info.qcstatus));
                        break;
                case SLIF_PLAYERS:
-                       dp_strlcpy( mask->info.players, str, sizeof(mask->info.players)  );
+                       mask->info.players_len = dp_strlcpy(mask->info.players, str, sizeof(mask->info.players));
                        break;
                case SLIF_MAP:
-                       dp_strlcpy( mask->info.map, str, sizeof(mask->info.map)  );
+                       mask->info.map_len = dp_strlcpy(mask->info.map, str, sizeof(mask->info.map));
                        break;
                case SLIF_MOD:
-                       dp_strlcpy( mask->info.mod, str, sizeof(mask->info.mod)  );
+                       mask->info.mod_len = dp_strlcpy(mask->info.mod, str, sizeof(mask->info.mod));
                        break;
                case SLIF_GAME:
-                       dp_strlcpy( mask->info.game, str, sizeof(mask->info.game)  );
+                       mask->info.game_len = dp_strlcpy(mask->info.game, str, sizeof(mask->info.game));
                        break;
                default:
                        VM_Warning(prog, "VM_M_setserverlistmaskstring: Bad field number %i passed!\n", field );
@@ -476,32 +476,32 @@ static void VM_M_getserverliststring(prvm_prog_t *prog)
        }
        switch( (int) PRVM_G_FLOAT(OFS_PARM0) ) {
                case SLIF_CNAME:
-                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( prog, cache->info.cname );
+                       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, cache->info.cname, cache->info.cname_len);
                        break;
                case SLIF_NAME:
-                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( prog, cache->info.name );
+                       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, cache->info.name, cache->info.name_len);
                        break;
                case SLIF_QCSTATUS:
-                       PRVM_G_INT (OFS_RETURN ) = PRVM_SetTempString( prog, cache->info.qcstatus );
+                       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, cache->info.qcstatus, cache->info.qcstatus_len);
                        break;
                case SLIF_PLAYERS:
-                       PRVM_G_INT (OFS_RETURN ) = PRVM_SetTempString( prog, cache->info.players );
+                       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, cache->info.players, cache->info.players_len);
                        break;
                case SLIF_GAME:
-                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( prog, cache->info.game );
+                       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, cache->info.game, cache->info.game_len);
                        break;
                case SLIF_MOD:
-                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( prog, cache->info.mod );
+                       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, cache->info.mod, cache->info.mod_len);
                        break;
                case SLIF_MAP:
-                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( prog, cache->info.map );
+                       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, cache->info.map, cache->info.map_len);
                        break;
                // TODO remove this again
                case 1024:
-                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( prog, cache->line1 );
+                       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, cache->line1, cache->line1_len);
                        break;
                case 1025:
-                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( prog, cache->line2 );
+                       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, cache->line2, cache->line2_len);
                        break;
                default:
                        Con_Print("VM_M_getserverliststring: bad field number passed!\n");
@@ -810,7 +810,7 @@ static void VM_M_crypto_getkeyfp(prvm_prog_t *prog)
        VM_CheckEmptyString( prog, s );
 
        if(LHNETADDRESS_FromString(&addr, s, 26000) && Crypto_RetrieveHostKey(&addr, NULL, keyfp, sizeof(keyfp), NULL, 0, NULL, NULL))
-               PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( prog, keyfp );
+               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, keyfp, strlen(keyfp));
        else
                PRVM_G_INT( OFS_RETURN ) = OFS_NULL;
 }
@@ -826,7 +826,7 @@ static void VM_M_crypto_getidfp(prvm_prog_t *prog)
        VM_CheckEmptyString( prog, s );
 
        if(LHNETADDRESS_FromString(&addr, s, 26000) && Crypto_RetrieveHostKey(&addr, NULL, NULL, 0, idfp, sizeof(idfp), NULL, NULL))
-               PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( prog, idfp );
+               PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString( prog, idfp, strlen(idfp));
        else
                PRVM_G_INT( OFS_RETURN ) = OFS_NULL;
 }
@@ -859,7 +859,15 @@ static void VM_M_crypto_getencryptlevel(prvm_prog_t *prog)
        VM_CheckEmptyString( prog, s );
 
        if(LHNETADDRESS_FromString(&addr, s, 26000) && Crypto_RetrieveHostKey(&addr, NULL, NULL, 0, NULL, 0, &aeslevel, NULL))
-               PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(prog, aeslevel ? va(vabuf, sizeof(vabuf), "%d AES128", aeslevel) : "0");
+       {
+               if (aeslevel)
+               {
+                       size_t vabuf_len = dpsnprintf(vabuf, sizeof(vabuf), "%d AES128", aeslevel);
+                       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, vabuf, vabuf_len);
+               }
+               else
+                       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, "0", 1);
+       }
        else
                PRVM_G_INT( OFS_RETURN ) = OFS_NULL;
 }
@@ -874,14 +882,14 @@ static void VM_M_crypto_getmykeyfp(prvm_prog_t *prog)
        switch(Crypto_RetrieveLocalKey(i, keyfp, sizeof(keyfp), NULL, 0, NULL))
        {
                case -1:
-                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(prog, "");
+                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(prog, "", 0);
                        break;
                case 0:
                        PRVM_G_INT( OFS_RETURN ) = OFS_NULL;
                        break;
                default:
                case 1:
-                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(prog, keyfp);
+                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(prog, keyfp, strlen(keyfp));
                        break;
        }
 }
@@ -896,14 +904,14 @@ static void VM_M_crypto_getmyidfp(prvm_prog_t *prog)
        switch(Crypto_RetrieveLocalKey(i, NULL, 0, idfp, sizeof(idfp), NULL))
        {
                case -1:
-                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(prog, "");
+                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(prog, "", 0);
                        break;
                case 0:
                        PRVM_G_INT( OFS_RETURN ) = OFS_NULL;
                        break;
                default:
                case 1:
-                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(prog, idfp);
+                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(prog, idfp, strlen(idfp));
                        break;
        }
 }
index c1e8bb96f7c2e2e3d7d0deaed73718991750892a..c21e1484249ae74a4c133d5d4cc5641dc6e04f88 100644 (file)
--- a/netconn.c
+++ b/netconn.c
@@ -1725,7 +1725,7 @@ static int NetConn_ClientParsePacket_ServerList_ProcessReply(const char *address
                entry = &serverlist_cache[n];
 
                memset(entry, 0, sizeof(*entry));
-               dp_strlcpy(entry->info.cname, addressstring, sizeof(entry->info.cname));
+               entry->info.cname_len = dp_strlcpy(entry->info.cname, addressstring, sizeof(entry->info.cname));
 
                // use the broadcast as the first query, NetConn_QueryQueueFrame() will send more
                entry->querytime = masterquerytime;
@@ -1785,14 +1785,14 @@ static void NetConn_ClientParsePacket_ServerList_UpdateCache(int n)
        serverlist_info_t *info = &entry->info;
 
        // update description strings for engine menu and console output
-       dpsnprintf(entry->line1, sizeof(serverlist_cache[n].line1), "^%c%5.0f^7 ^%c%3u^7/%3u %-65.65s",
+       entry->line1_len = dpsnprintf(entry->line1, sizeof(serverlist_cache[n].line1), "^%c%5.0f^7 ^%c%3u^7/%3u %-65.65s",
                   info->ping >= 300 ? '1' : (info->ping >= 200 ? '3' : '7'),
                   info->ping ?: INFINITY, // display inf when a listed server times out and net_slist_pause blocks its removal
                   ((info->numhumans > 0 && info->numhumans < info->maxplayers) ? (info->numhumans >= 4 ? '7' : '3') : '1'),
                   info->numplayers,
                   info->maxplayers,
                   info->name);
-       dpsnprintf(entry->line2, sizeof(serverlist_cache[n].line2), "^4%-21.21s %-19.19s ^%c%-17.17s^4 %-20.20s", info->cname, info->game,
+       entry->line2_len = dpsnprintf(entry->line2, sizeof(serverlist_cache[n].line2), "^4%-21.21s %-19.19s ^%c%-17.17s^4 %-20.20s", info->cname, info->game,
                        (
                         info->gameversion != gameversion.integer
                         &&
@@ -1842,7 +1842,7 @@ static qbool NetConn_ClientParsePacket_ServerList_PrepareQuery(int protocol, con
        entry = &serverlist_cache[n];
        memset(entry, 0, sizeof(*entry));
        entry->protocol = protocol;
-       dp_strlcpy(entry->info.cname, ipstring, sizeof(entry->info.cname));
+       entry->info.cname_len = dp_strlcpy(entry->info.cname, ipstring, sizeof(entry->info.cname));
        entry->info.isfavorite = isfavorite;
 
        serverlist_cachecount++;
@@ -2175,15 +2175,15 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat
                                        return true;
 
                                info = &serverlist_cache[n].info;
-                               info->game[0] = 0;
-                               info->mod[0]  = 0;
-                               info->map[0]  = 0;
-                               info->name[0] = 0;
-                               info->qcstatus[0] = 0;
-                               info->players[0] = 0;
-                               info->protocol = -1;
-                               info->numplayers = 0;
-                               info->numbots = -1;
+                               info->game[0]     = '\0'; info->game_len = 0;
+                               info->mod[0]      = '\0'; info->mod_len = 0;
+                               info->map[0]      = '\0'; info->map_len = 0;
+                               info->name[0]     = '\0'; info->name_len = 0;
+                               info->qcstatus[0] = '\0'; info->qcstatus_len = 0;
+                               info->players[0]  = '\0'; info->players_len = 0;
+                               info->protocol    = -1;
+                               info->numplayers  = 0;
+                               info->numbots     = -1;
                                info->maxplayers  = 0;
                                info->gameversion = 0;
 
@@ -2196,17 +2196,17 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat
                                else
                                        Con_Printf("statusResponse without players block?\n");
 
-                               if ((s = InfoString_GetValue(string, "gamename"     , infostringvalue, sizeof(infostringvalue))) != NULL) dp_strlcpy(info->game, s, sizeof (info->game));
-                               if ((s = InfoString_GetValue(string, "modname"      , infostringvalue, sizeof(infostringvalue))) != NULL) dp_strlcpy(info->mod , s, sizeof (info->mod ));
-                               if ((s = InfoString_GetValue(string, "mapname"      , infostringvalue, sizeof(infostringvalue))) != NULL) dp_strlcpy(info->map , s, sizeof (info->map ));
-                               if ((s = InfoString_GetValue(string, "hostname"     , infostringvalue, sizeof(infostringvalue))) != NULL) dp_strlcpy(info->name, s, sizeof (info->name));
+                               if ((s = InfoString_GetValue(string, "gamename"     , infostringvalue, sizeof(infostringvalue))) != NULL) info->game_len = dp_strlcpy(info->game, s, sizeof(info->game));
+                               if ((s = InfoString_GetValue(string, "modname"      , infostringvalue, sizeof(infostringvalue))) != NULL) info->mod_len = dp_strlcpy(info->mod, s, sizeof(info->mod));
+                               if ((s = InfoString_GetValue(string, "mapname"      , infostringvalue, sizeof(infostringvalue))) != NULL) info->map_len = dp_strlcpy(info->map, s, sizeof(info->map));
+                               if ((s = InfoString_GetValue(string, "hostname"     , infostringvalue, sizeof(infostringvalue))) != NULL) info->name_len = dp_strlcpy(info->name, s, sizeof(info->name));
                                if ((s = InfoString_GetValue(string, "protocol"     , infostringvalue, sizeof(infostringvalue))) != NULL) info->protocol = atoi(s);
                                if ((s = InfoString_GetValue(string, "clients"      , infostringvalue, sizeof(infostringvalue))) != NULL) info->numplayers = atoi(s);
                                if ((s = InfoString_GetValue(string, "bots"         , infostringvalue, sizeof(infostringvalue))) != NULL) info->numbots = atoi(s);
                                if ((s = InfoString_GetValue(string, "sv_maxclients", infostringvalue, sizeof(infostringvalue))) != NULL) info->maxplayers = atoi(s);
                                if ((s = InfoString_GetValue(string, "gameversion"  , infostringvalue, sizeof(infostringvalue))) != NULL) info->gameversion = atoi(s);
-                               if ((s = InfoString_GetValue(string, "qcstatus"     , infostringvalue, sizeof(infostringvalue))) != NULL) dp_strlcpy(info->qcstatus, s, sizeof(info->qcstatus));
-                               if (p                                                                                         != NULL) dp_strlcpy(info->players, p, sizeof(info->players));
+                               if ((s = InfoString_GetValue(string, "qcstatus"     , infostringvalue, sizeof(infostringvalue))) != NULL) info->qcstatus_len = dp_strlcpy(info->qcstatus, s, sizeof(info->qcstatus));
+                               if (p                                                                                            != NULL) info->players_len = dp_strlcpy(info->players, p, sizeof(info->players));
                                info->numhumans = info->numplayers - max(0, info->numbots);
                                info->freeslots = info->maxplayers - info->numplayers;
 
@@ -2228,28 +2228,28 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat
                                        return true;
 
                                info = &serverlist_cache[n].info;
-                               info->game[0] = 0;
-                               info->mod[0]  = 0;
-                               info->map[0]  = 0;
-                               info->name[0] = 0;
-                               info->qcstatus[0] = 0;
-                               info->players[0] = 0;
-                               info->protocol = -1;
-                               info->numplayers = 0;
-                               info->numbots = -1;
+                               info->game[0]     = '\0'; info->game_len = 0;
+                               info->mod[0]      = '\0'; info->mod_len = 0;
+                               info->map[0]      = '\0'; info->map_len = 0;
+                               info->name[0]     = '\0'; info->name_len = 0;
+                               info->qcstatus[0] = '\0'; info->qcstatus_len = 0;
+                               info->players[0]  = '\0'; info->players_len = 0;
+                               info->protocol    = -1;
+                               info->numplayers  = 0;
+                               info->numbots     = -1;
                                info->maxplayers  = 0;
                                info->gameversion = 0;
 
-                               if ((s = InfoString_GetValue(string, "gamename"     , infostringvalue, sizeof(infostringvalue))) != NULL) dp_strlcpy(info->game, s, sizeof (info->game));
-                               if ((s = InfoString_GetValue(string, "modname"      , infostringvalue, sizeof(infostringvalue))) != NULL) dp_strlcpy(info->mod , s, sizeof (info->mod ));
-                               if ((s = InfoString_GetValue(string, "mapname"      , infostringvalue, sizeof(infostringvalue))) != NULL) dp_strlcpy(info->map , s, sizeof (info->map ));
-                               if ((s = InfoString_GetValue(string, "hostname"     , infostringvalue, sizeof(infostringvalue))) != NULL) dp_strlcpy(info->name, s, sizeof (info->name));
+                               if ((s = InfoString_GetValue(string, "gamename"     , infostringvalue, sizeof(infostringvalue))) != NULL) info->game_len = dp_strlcpy(info->game, s, sizeof(info->game));
+                               if ((s = InfoString_GetValue(string, "modname"      , infostringvalue, sizeof(infostringvalue))) != NULL) info->mod_len = dp_strlcpy(info->mod, s, sizeof(info->mod));
+                               if ((s = InfoString_GetValue(string, "mapname"      , infostringvalue, sizeof(infostringvalue))) != NULL) info->map_len = dp_strlcpy(info->map, s, sizeof(info->map));
+                               if ((s = InfoString_GetValue(string, "hostname"     , infostringvalue, sizeof(infostringvalue))) != NULL) info->name_len = dp_strlcpy(info->name, s, sizeof(info->name));
                                if ((s = InfoString_GetValue(string, "protocol"     , infostringvalue, sizeof(infostringvalue))) != NULL) info->protocol = atoi(s);
                                if ((s = InfoString_GetValue(string, "clients"      , infostringvalue, sizeof(infostringvalue))) != NULL) info->numplayers = atoi(s);
                                if ((s = InfoString_GetValue(string, "bots"         , infostringvalue, sizeof(infostringvalue))) != NULL) info->numbots = atoi(s);
                                if ((s = InfoString_GetValue(string, "sv_maxclients", infostringvalue, sizeof(infostringvalue))) != NULL) info->maxplayers = atoi(s);
                                if ((s = InfoString_GetValue(string, "gameversion"  , infostringvalue, sizeof(infostringvalue))) != NULL) info->gameversion = atoi(s);
-                               if ((s = InfoString_GetValue(string, "qcstatus"     , infostringvalue, sizeof(infostringvalue))) != NULL) dp_strlcpy(info->qcstatus, s, sizeof(info->qcstatus));
+                               if ((s = InfoString_GetValue(string, "qcstatus"     , infostringvalue, sizeof(infostringvalue))) != NULL) info->qcstatus_len = dp_strlcpy(info->qcstatus, s, sizeof(info->qcstatus));
                                info->numhumans = info->numplayers - max(0, info->numbots);
                                info->freeslots = info->maxplayers - info->numplayers;
 
@@ -2348,9 +2348,12 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat
 
                        info = &serverlist_cache[n].info;
                        dp_strlcpy(info->game, "QuakeWorld", sizeof(info->game));
-                       if ((s = InfoString_GetValue(string, "*gamedir"     , infostringvalue, sizeof(infostringvalue))) != NULL) dp_strlcpy(info->mod , s, sizeof (info->mod ));else info->mod[0]  = 0;
-                       if ((s = InfoString_GetValue(string, "map"          , infostringvalue, sizeof(infostringvalue))) != NULL) dp_strlcpy(info->map , s, sizeof (info->map ));else info->map[0]  = 0;
-                       if ((s = InfoString_GetValue(string, "hostname"     , infostringvalue, sizeof(infostringvalue))) != NULL) dp_strlcpy(info->name, s, sizeof (info->name));else info->name[0] = 0;
+                       if ((s = InfoString_GetValue(string, "*gamedir"     , infostringvalue, sizeof(infostringvalue))) != NULL) info->mod_len = dp_strlcpy(info->mod, s, sizeof(info->mod));
+                       else { info->mod[0] = '\0'; info->mod_len = 0; }
+                       if ((s = InfoString_GetValue(string, "map"          , infostringvalue, sizeof(infostringvalue))) != NULL) info->map_len = dp_strlcpy(info->map, s, sizeof(info->map));
+                       else { info->map[0] = '\0'; info->map_len = 0; }
+                       if ((s = InfoString_GetValue(string, "hostname"     , infostringvalue, sizeof(infostringvalue))) != NULL) info->name_len = dp_strlcpy(info->name, s, sizeof(info->name));
+                       else { info->name[0] = '\0'; info->name_len = 0; }
                        info->protocol = 0;
                        info->numplayers = 0; // updated below
                        info->numhumans = 0; // updated below
@@ -2470,10 +2473,10 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat
                                break;
 
                        info = &serverlist_cache[n].info;
-                       dp_strlcpy(info->game, "Quake", sizeof(info->game));
-                       dp_strlcpy(info->mod , "", sizeof(info->mod)); // mod name is not specified
-                       dp_strlcpy(info->name, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof(info->name));
-                       dp_strlcpy(info->map , MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof(info->map));
+                       info->game_len = dp_strlcpy(info->game, "Quake", sizeof(info->game));
+                       info->mod_len  = dp_strlcpy(info->mod, "", sizeof(info->mod)); // mod name is not specified
+                       info->name_len = dp_strlcpy(info->name, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof(info->name));
+                       info->map_len  = dp_strlcpy(info->map, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof(info->map));
                        info->numplayers = MSG_ReadByte(&cl_message);
                        info->maxplayers = MSG_ReadByte(&cl_message);
                        info->protocol = MSG_ReadByte(&cl_message);
index a70bf5b4a9d351f58f5d45c11847e511ce1d4cbb..a7ef91d22d59999492f7490d8004dd0c75b90db7 100755 (executable)
--- a/netconn.h
+++ b/netconn.h
@@ -274,20 +274,27 @@ typedef struct serverlist_info_s
 {
        /// address for connecting
        char cname[128];
+       unsigned cname_len;
        /// ping time for sorting servers, in milliseconds, 0 means no data
        unsigned ping;
        /// name of the game
        char game[32];
+       unsigned game_len;
        /// name of the mod
        char mod[32];
+       unsigned mod_len;
        /// name of the map
        char map[32];
+       unsigned map_len;
        /// name of the session
        char name[128];
+       unsigned name_len;
        /// qc-defined short status string
        char qcstatus[128];
+       unsigned qcstatus_len;
        /// frags/ping/name list (if they fit in the packet)
        char players[2800];
+       unsigned players_len;
        /// max client number
        int maxplayers;
        /// number of currently connected players (including bots)
@@ -352,7 +359,9 @@ typedef struct serverlist_entry_s
 
        // legacy stuff
        char line1[128];
+       unsigned line1_len;
        char line2[128];
+       unsigned line2_len;
 } serverlist_entry_t;
 
 typedef struct serverlist_mask_s
index 92ead5dc772a8393f7a7470fee8cec35be11a78c..4c6a7f4d34ea4b407bf1f8e1203d7f9dbf893338 100644 (file)
--- a/progsvm.h
+++ b/progsvm.h
@@ -901,7 +901,8 @@ void PRVM_ED_PrintNum (prvm_prog_t *prog, int ent, const char *wildcard_fieldnam
 const char *PRVM_GetString(prvm_prog_t *prog, int num);
 int PRVM_SetEngineString(prvm_prog_t *prog, const char *s);
 const char *PRVM_ChangeEngineString(prvm_prog_t *prog, int i, const char *s);
-int PRVM_SetTempString(prvm_prog_t *prog, const char *s);
+/// Takes an strlen (not a buffer size).
+int PRVM_SetTempString(prvm_prog_t *prog, const char *s, size_t slen);
 int PRVM_AllocString(prvm_prog_t *prog, size_t bufferlength, char **pointer);
 void PRVM_FreeString(prvm_prog_t *prog, int num);
 
index dcf2dccfc61691dc2da329884b435ffc156db7d6..aefac6720752672d703bcb45b87a28f6fa3c2ebf 100644 (file)
@@ -65,7 +65,7 @@ void VM_CheckEmptyString(prvm_prog_t *prog, const char *s)
                prog->error_cmd("%s: Bad string", prog->name);
 }
 
-qbool PRVM_ConsoleCommand (prvm_prog_t *prog, const char *text, int *func, qbool preserve_self, int curself, double ptime, qbool prog_loaded, const char *error_message)
+qbool PRVM_ConsoleCommand(prvm_prog_t *prog, const char *text, size_t textlen, int *func, qbool preserve_self, int curself, double ptime, qbool prog_loaded, const char *error_message)
 {
        int restorevm_tempstringsbuf_cursize;
        int save_self = 0; // hush compiler warning
@@ -82,7 +82,7 @@ qbool PRVM_ConsoleCommand (prvm_prog_t *prog, const char *text, int *func, qbool
                        PRVM_gameglobalfloat(time) = ptime;
                PRVM_gameglobaledict(self) = curself;
                restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize;
-               PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(prog, text);
+               PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(prog, text, textlen);
                prog->ExecuteProgram(prog, *func, error_message);
                prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
                if(preserve_self)
@@ -778,11 +778,18 @@ const string      VM_cvar_string (string, ...)
 */
 void VM_cvar_string(prvm_prog_t *prog)
 {
-       char string[VM_TEMPSTRING_MAXSIZE];
+       char cvar_name[VM_TEMPSTRING_MAXSIZE];
+
        VM_SAFEPARMCOUNTRANGE(1,8,VM_cvar_string);
-       VM_VarString(prog, 0, string, sizeof(string));
-       VM_CheckEmptyString(prog, string);
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, PRVM_Cvar_ReadOk(prog, string) ? Cvar_VariableString(prog->console_cmd->cvars, string, prog->console_cmd->cvars_flagsmask) : "");
+       VM_VarString(prog, 0, cvar_name, sizeof(cvar_name));
+       VM_CheckEmptyString(prog, cvar_name);
+       if (PRVM_Cvar_ReadOk(prog, cvar_name))
+       {
+               const char *cvar_string = Cvar_VariableString(prog->console_cmd->cvars, cvar_name, prog->console_cmd->cvars_flagsmask);
+               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, cvar_string, strlen(cvar_string));
+       }
+       else
+               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, "", 0);
 }
 
 
@@ -795,11 +802,14 @@ const string      VM_cvar_defstring (string, ...)
 */
 void VM_cvar_defstring(prvm_prog_t *prog)
 {
-       char string[VM_TEMPSTRING_MAXSIZE];
+       char cvar_name[VM_TEMPSTRING_MAXSIZE];
+       const char *cvar_defstring;
+
        VM_SAFEPARMCOUNTRANGE(1,8,VM_cvar_defstring);
-       VM_VarString(prog, 0, string, sizeof(string));
-       VM_CheckEmptyString(prog, string);
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, Cvar_VariableDefString(prog->console_cmd->cvars, string, prog->console_cmd->cvars_flagsmask));
+       VM_VarString(prog, 0, cvar_name, sizeof(cvar_name));
+       VM_CheckEmptyString(prog, cvar_name);
+       cvar_defstring = Cvar_VariableDefString(prog->console_cmd->cvars, cvar_name, prog->console_cmd->cvars_flagsmask);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, cvar_defstring, strlen(cvar_defstring));
 }
 
 /*
@@ -811,11 +821,14 @@ const string      VM_cvar_description (string, ...)
 */
 void VM_cvar_description(prvm_prog_t *prog)
 {
-       char string[VM_TEMPSTRING_MAXSIZE];
+       char cvar_name[VM_TEMPSTRING_MAXSIZE];
+       const char *cvar_desc;
+
        VM_SAFEPARMCOUNTRANGE(1,8,VM_cvar_description);
-       VM_VarString(prog, 0, string, sizeof(string));
-       VM_CheckEmptyString(prog, string);
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, Cvar_VariableDescription(prog->console_cmd->cvars, string, prog->console_cmd->cvars_flagsmask));
+       VM_VarString(prog, 0, cvar_name, sizeof(cvar_name));
+       VM_CheckEmptyString(prog, cvar_name);
+       cvar_desc = Cvar_VariableDescription(prog->console_cmd->cvars, cvar_name, prog->console_cmd->cvars_flagsmask);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, cvar_desc, strlen(cvar_desc));
 }
 /*
 =================
@@ -879,16 +892,17 @@ void VM_ftos(prvm_prog_t *prog)
 {
        prvm_vec_t v;
        char s[128];
+       size_t slen;
 
        VM_SAFEPARMCOUNT(1, VM_ftos);
 
        v = PRVM_G_FLOAT(OFS_PARM0);
 
        if ((prvm_vec_t)((prvm_int_t)v) == v)
-               dpsnprintf(s, sizeof(s), "%.0f", v);
+               slen = dpsnprintf(s, sizeof(s), "%.0f", v);
        else
-               dpsnprintf(s, sizeof(s), "%f", v);
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, s);
+               slen = dpsnprintf(s, sizeof(s), "%f", v);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, s, slen);
 }
 
 /*
@@ -920,11 +934,12 @@ string    vtos(vector)
 void VM_vtos(prvm_prog_t *prog)
 {
        char s[512];
+       size_t slen;
 
        VM_SAFEPARMCOUNT(1,VM_vtos);
 
-       dpsnprintf (s, sizeof(s), "'%5.1f %5.1f %5.1f'", PRVM_G_VECTOR(OFS_PARM0)[0], PRVM_G_VECTOR(OFS_PARM0)[1], PRVM_G_VECTOR(OFS_PARM0)[2]);
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, s);
+       slen = dpsnprintf(s, sizeof(s), "'%5.1f %5.1f %5.1f'", PRVM_G_VECTOR(OFS_PARM0)[0], PRVM_G_VECTOR(OFS_PARM0)[1], PRVM_G_VECTOR(OFS_PARM0)[2]);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, s, slen);
 }
 
 /*
@@ -938,11 +953,12 @@ string    etos(entity)
 void VM_etos(prvm_prog_t *prog)
 {
        char s[128];
+       size_t slen;
 
        VM_SAFEPARMCOUNT(1, VM_etos);
 
-       dpsnprintf (s, sizeof(s), "entity %i", PRVM_G_EDICTNUM(OFS_PARM0));
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, s);
+       slen = dpsnprintf(s, sizeof(s), "entity %i", PRVM_G_EDICTNUM(OFS_PARM0));
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, s, slen);
 }
 
 /*
@@ -1023,6 +1039,8 @@ void VM_strftime(prvm_prog_t *prog)
 #endif
        char fmt[VM_TEMPSTRING_MAXSIZE];
        char result[VM_TEMPSTRING_MAXSIZE];
+       size_t result_len;
+
        VM_SAFEPARMCOUNTRANGE(2, 8, VM_strftime);
        VM_VarString(prog, 1, fmt, sizeof(fmt));
        t = time(NULL);
@@ -1044,11 +1062,11 @@ void VM_strftime(prvm_prog_t *prog)
                return;
        }
 #if _MSC_VER >= 1400
-       strftime(result, sizeof(result), fmt, &tm);
+       result_len = strftime(result, sizeof(result), fmt, &tm);
 #else
-       strftime(result, sizeof(result), fmt, tm);
+       result_len = strftime(result, sizeof(result), fmt, tm);
 #endif
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, result);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, result, result_len);
 }
 
 /*
@@ -2023,7 +2041,7 @@ void VM_fgets(prvm_prog_t *prog)
                if (end < VM_TEMPSTRING_MAXSIZE - 1)
                        string[end++] = c;
        }
-       string[end] = 0;
+       string[end] = '\0';
        // remove \n following \r
        if (c == '\r')
        {
@@ -2034,7 +2052,7 @@ void VM_fgets(prvm_prog_t *prog)
        if (developer_extra.integer)
                Con_DPrintf("fgets: %s: %s\n", prog->name, string);
        if (c >= 0 || end)
-               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
+               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string, end);
 }
 
 /*
@@ -2133,7 +2151,7 @@ void VM_entityfieldname(prvm_prog_t *prog)
        if (i < 0 || i >= prog->numfielddefs)
        {
                VM_Warning(prog, "VM_entityfieldname: %s: field index out of bounds\n", prog->name);
-               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, "");
+               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, "", 0);
                return;
        }
 
@@ -2185,8 +2203,8 @@ void VM_getentityfieldstring(prvm_prog_t *prog)
        
        if (i < 0 || i >= prog->numfielddefs)
        {
-        VM_Warning(prog, "VM_entityfielddata: %s: field index out of bounds\n", prog->name);
-               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, "");
+               VM_Warning(prog, "VM_entityfielddata: %s: field index out of bounds\n", prog->name);
+               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, "", 0);
                return;
        }
        
@@ -2196,7 +2214,7 @@ void VM_getentityfieldstring(prvm_prog_t *prog)
        ent = PRVM_G_EDICT(OFS_PARM1);
        if(ent->free)
        {
-               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, "");
+               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, "", 0);
                VM_Warning(prog, "VM_entityfielddata: %s: entity %i is free !\n", prog->name, PRVM_NUM_FOR_EDICT(ent));
                return;
        }
@@ -2209,11 +2227,12 @@ void VM_getentityfieldstring(prvm_prog_t *prog)
                        break;
        if (j == prvm_type_size[type])
        {
-               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, "");
+               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, "", 0);
                return;
        }
-               
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, PRVM_UglyValueString(prog, (etype_t)d->type, val, valuebuf, sizeof(valuebuf)));
+
+       PRVM_UglyValueString(prog, (etype_t)d->type, val, valuebuf, sizeof(valuebuf));
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, valuebuf, strlen(valuebuf));
 }
 
 // KrimZon - DP_QC_ENTITYDATA
@@ -2280,13 +2299,14 @@ string  strdecolorize(string s)
 void VM_strdecolorize(prvm_prog_t *prog)
 {
        char szNewString[VM_TEMPSTRING_MAXSIZE];
+       size_t szNewString_len;
        const char *szString;
 
        // Prepare Strings
        VM_SAFEPARMCOUNT(1,VM_strdecolorize);
        szString = PRVM_G_STRING(OFS_PARM0);
-       COM_StringDecolorize(szString, 0, szNewString, sizeof(szNewString), true);
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, szNewString);
+       szNewString_len = COM_StringDecolorize(szString, 0, szNewString, sizeof(szNewString), true);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, szNewString, szNewString_len);
 }
 
 // DRESK - String Length (not counting color codes)
@@ -2326,15 +2346,16 @@ string  strtolower(string s)
 void VM_strtolower(prvm_prog_t *prog)
 {
        char szNewString[VM_TEMPSTRING_MAXSIZE];
+       size_t szNewString_len;
        const char *szString;
 
        // Prepare Strings
        VM_SAFEPARMCOUNT(1,VM_strtolower);
        szString = PRVM_G_STRING(OFS_PARM0);
 
-       COM_ToLowerString(szString, szNewString, sizeof(szNewString) );
+       szNewString_len = COM_ToLowerString(szString, szNewString, sizeof(szNewString) );
 
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, szNewString);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, szNewString, szNewString_len);
 }
 
 /*
@@ -2348,15 +2369,16 @@ string  strtoupper(string s)
 void VM_strtoupper(prvm_prog_t *prog)
 {
        char szNewString[VM_TEMPSTRING_MAXSIZE];
+       size_t szNewString_len;
        const char *szString;
 
        // Prepare Strings
        VM_SAFEPARMCOUNT(1,VM_strtoupper);
        szString = PRVM_G_STRING(OFS_PARM0);
 
-       COM_ToUpperString(szString, szNewString, sizeof(szNewString) );
+       szNewString_len = COM_ToUpperString(szString, szNewString, sizeof(szNewString) );
 
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, szNewString);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, szNewString, szNewString_len);
 }
 
 /*
@@ -2372,10 +2394,12 @@ string strcat(string s, string...)
 void VM_strcat(prvm_prog_t *prog)
 {
        char s[VM_TEMPSTRING_MAXSIZE];
+       size_t slen;
+
        VM_SAFEPARMCOUNTRANGE(1, 8, VM_strcat);
 
-       VM_VarString(prog, 0, s, sizeof(s));
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, s);
+       slen = VM_VarString(prog, 0, s, sizeof(s));
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, s, slen);
 }
 
 /*
@@ -2439,7 +2463,7 @@ void VM_substring(prvm_prog_t *prog)
        u_start = u8_byteofs(s, start, NULL);
        if (u_start < 0)
        {
-               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, "");
+               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, "", 0);
                return;
        }
        u_length = u8_bytelen(s + u_start, length);
@@ -2447,8 +2471,8 @@ void VM_substring(prvm_prog_t *prog)
                u_length = sizeof(string)-1;
        
        memcpy(string, s + u_start, u_length);
-       string[u_length] = 0;
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
+       string[u_length] = '\0';
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string, u_length);
 }
 
 /*
@@ -2515,7 +2539,7 @@ void VM_strreplace(prvm_prog_t *prog)
                        string[si++] = subject[i];
        string[si] = '\0';
 
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string, si);
 }
 
 /*
@@ -2582,7 +2606,7 @@ void VM_strireplace(prvm_prog_t *prog)
                        string[si++] = subject[i];
        string[si] = '\0';
 
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string, si);
 }
 
 /*
@@ -2676,7 +2700,7 @@ void VM_tokenize (prvm_prog_t *prog)
                if(!COM_ParseToken_VM_Tokenize(&p, false))
                        break;
                tokens_endpos[num_tokens] = p - tokenize_string;
-               tokens[num_tokens] = PRVM_SetTempString(prog, com_token);
+               tokens[num_tokens] = PRVM_SetTempString(prog, com_token, com_token_len);
                ++num_tokens;
        }
 
@@ -2707,7 +2731,7 @@ void VM_tokenize_console (prvm_prog_t *prog)
                if(!COM_ParseToken_Console(&p))
                        break;
                tokens_endpos[num_tokens] = p - tokenize_string;
-               tokens[num_tokens] = PRVM_SetTempString(prog, com_token);
+               tokens[num_tokens] = PRVM_SetTempString(prog, com_token, com_token_len);
                ++num_tokens;
        }
 
@@ -2783,8 +2807,8 @@ void VM_tokenizebyseparator (prvm_prog_t *prog)
                tokens_endpos[num_tokens] = p0 - tokenize_string;
                if (j >= (int)sizeof(tokentext))
                        break;
-               tokentext[j++] = 0;
-               tokens[num_tokens++] = PRVM_SetTempString(prog, token);
+               tokentext[j++] = '\0';
+               tokens[num_tokens++] = PRVM_SetTempString(prog, token, j - 1);
                if (!*p)
                        break;
        }
@@ -3259,6 +3283,7 @@ string    search_getfilename(float handle, float num)
 void VM_search_getfilename(prvm_prog_t *prog)
 {
        int handle, filenum;
+
        VM_SAFEPARMCOUNT(2, VM_search_getfilename);
 
        handle = (int)PRVM_G_FLOAT(OFS_PARM0);
@@ -3280,7 +3305,9 @@ void VM_search_getfilename(prvm_prog_t *prog)
                return;
        }
 
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, prog->opensearches[handle]->filenames[filenum]);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog,
+                                                   prog->opensearches[handle]->filenames[filenum],
+                                                   strlen(prog->opensearches[handle]->filenames[filenum]));
 }
 
 /*
@@ -3304,11 +3331,11 @@ void VM_chr(prvm_prog_t *prog)
        
        char tmp[8];
        int len;
-       VM_SAFEPARMCOUNT(1, VM_chr);
 
+       VM_SAFEPARMCOUNT(1, VM_chr);
        len = u8_fromchar((Uchar)PRVM_G_FLOAT(OFS_PARM0), tmp, sizeof(tmp));
-       tmp[len] = 0;
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, tmp);
+       tmp[len] = '\0';
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, tmp, len);
 }
 
 /*
@@ -3321,9 +3348,11 @@ string keynumtostring(float keynum)
 void VM_keynumtostring (prvm_prog_t *prog)
 {
        char tinystr[TINYSTR_LEN];
-       VM_SAFEPARMCOUNT(1, VM_keynumtostring);
+       const char *str; // Key_KeynumToString doesn't always return tinystr
 
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, Key_KeynumToString((int)PRVM_G_FLOAT(OFS_PARM0), tinystr, TINYSTR_LEN));
+       VM_SAFEPARMCOUNT(1, VM_keynumtostring);
+       str = Key_KeynumToString((int)PRVM_G_FLOAT(OFS_PARM0), tinystr, sizeof(tinystr));
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, str, strlen(str));
 }
 
 /*
@@ -3341,6 +3370,7 @@ void VM_findkeysforcommand(prvm_prog_t *prog)
 {
        const char *cmd;
        char ret[VM_TEMPSTRING_MAXSIZE];
+       size_t ret_len;
        int keys[FKFC_NUMKEYS];
        int i;
        int bindmap;
@@ -3360,9 +3390,9 @@ void VM_findkeysforcommand(prvm_prog_t *prog)
 
        ret[0] = 0;
        for(i = 0; i < FKFC_NUMKEYS; i++)
-               dp_strlcat(ret, va(vabuf, sizeof(vabuf), " \'%i\'", keys[i]), sizeof(ret));
+               ret_len = dp_strlcat(ret, va(vabuf, sizeof(vabuf), " \'%i\'", keys[i]), sizeof(ret));
 
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, ret);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, ret, ret_len);
 }
 
 /*
@@ -3389,13 +3419,15 @@ string getkeybind(float key, float bindmap)
 void VM_getkeybind (prvm_prog_t *prog)
 {
        int bindmap;
+       const char *bind;
+
        VM_SAFEPARMCOUNTRANGE(1, 2, VM_getkeybind);
        if(prog->argc == 2)
                bindmap = bound(-1, PRVM_G_FLOAT(OFS_PARM1), MAX_BINDMAPS-1);
        else
                bindmap = 0; // consistent to "bind"
-
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, Key_GetBind((int)PRVM_G_FLOAT(OFS_PARM0), bindmap));
+       bind = Key_GetBind((int)PRVM_G_FLOAT(OFS_PARM0), bindmap);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, bind, strlen(bind));
 }
 
 /*
@@ -3653,9 +3685,9 @@ void VM_altstr_prepare(prvm_prog_t *prog)
                else
                        outstr[outpos++] = *in;
        }
-       outstr[outpos] = 0;
 
-       PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(prog,  outstr );
+       outstr[outpos] = '\0';
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, outstr, outpos);
 }
 
 /*
@@ -3702,8 +3734,8 @@ void VM_altstr_get(prvm_prog_t *prog)
                else
                        *out = *pos;
 
-       *out = 0;
-       PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(prog,  outstr );
+       *out = '\0';
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, outstr, out - outstr);
 }
 
 /*
@@ -3746,8 +3778,8 @@ void VM_altstr_set(prvm_prog_t *prog)
                if( *in == '\'' || (*in == '\\' && !*++in) )
                        break;
 
-       dp_strlcpy(out, in, outstr + sizeof(outstr) - out);
-       PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(prog,  outstr );
+       out += dp_strlcpy(out, in, outstr + sizeof(outstr) - out);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, outstr, out - outstr);
 }
 
 /*
@@ -3785,8 +3817,8 @@ void VM_altstr_ins(prvm_prog_t *prog)
        for( ; *set ; *out++ = *set++ );
        *out++ = '\'';
 
-       dp_strlcpy(out, in, outstr + sizeof(outstr) - out);
-       PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(prog,  outstr );
+       out += dp_strlcpy(out, in, outstr + sizeof(outstr) - out);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, outstr, out - outstr);
 }
 
 
@@ -4113,10 +4145,12 @@ string buf_implode(float bufhandle, string glue) = #465;
 void VM_buf_implode (prvm_prog_t *prog)
 {
        prvm_stringbuffer_t *stringbuffer;
-       char                    k[VM_TEMPSTRING_MAXSIZE];
-       const char              *sep;
-       int                             i;
-       size_t                  l;
+       char k[VM_TEMPSTRING_MAXSIZE];
+       size_t k_len;
+       const char *sep;
+       int i;
+       size_t l;
+
        VM_SAFEPARMCOUNT(2, VM_buf_implode);
 
        stringbuffer = (prvm_stringbuffer_t *)Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, (int)PRVM_G_FLOAT(OFS_PARM0));
@@ -4129,7 +4163,8 @@ void VM_buf_implode (prvm_prog_t *prog)
        if(!stringbuffer->num_strings)
                return;
        sep = PRVM_G_STRING(OFS_PARM1);
-       k[0] = 0;
+       k[0] = '\0';
+       k_len = 0;
        for(l = i = 0;i < stringbuffer->num_strings;i++)
        {
                if(stringbuffer->strings[i])
@@ -4138,10 +4173,10 @@ void VM_buf_implode (prvm_prog_t *prog)
                        if (l >= sizeof(k) - 1)
                                break;
                        dp_strlcat(k, sep, sizeof(k));
-                       dp_strlcat(k, stringbuffer->strings[i], sizeof(k));
+                       k_len = dp_strlcat(k, stringbuffer->strings[i], sizeof(k));
                }
        }
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, k);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, k, k_len);
 }
 
 /*
@@ -4171,7 +4206,7 @@ void VM_bufstr_get (prvm_prog_t *prog)
                return;
        }
        if (strindex < stringbuffer->num_strings && stringbuffer->strings[strindex])
-               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, stringbuffer->strings[strindex]);
+               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, stringbuffer->strings[strindex], strlen(stringbuffer->strings[strindex]));
 }
 
 /*
@@ -4839,14 +4874,14 @@ void VM_changepitch (prvm_prog_t *prog)
 void VM_uncolorstring (prvm_prog_t *prog)
 {
        char szNewString[VM_TEMPSTRING_MAXSIZE];
+       size_t szNewString_len;
        const char *szString;
 
        // Prepare Strings
        VM_SAFEPARMCOUNT(1, VM_uncolorstring);
        szString = PRVM_G_STRING(OFS_PARM0);
-       COM_StringDecolorize(szString, 0, szNewString, sizeof(szNewString), true);
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, szNewString);
-       
+       szNewString_len = COM_StringDecolorize(szString, 0, szNewString, sizeof(szNewString), true);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, szNewString, szNewString_len);
 }
 
 // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
@@ -4911,11 +4946,12 @@ void VM_chr2str (prvm_prog_t *prog)
        char t[9 * 4 + 1];
        int i;
        size_t len = 0;
+
        VM_SAFEPARMCOUNTRANGE(0, 8, VM_chr2str);
        for(i = 0; i < prog->argc && len < sizeof(t)-1; ++i)
                len += u8_fromchar((Uchar)PRVM_G_FLOAT(OFS_PARM0+i*3), t + len, sizeof(t)-1);
-       t[len] = 0;
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, t);
+       t[len] = '\0';
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, t, len);
 }
 
 static int chrconv_number(int i, int base, int conv)
@@ -5044,7 +5080,7 @@ void VM_strconv (prvm_prog_t *prog)
        }
        *result = '\0';
 
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, (char *) resbuf);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, (char *)resbuf, result - resbuf);
 }
 
 // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
@@ -5052,16 +5088,18 @@ void VM_strpad (prvm_prog_t *prog)
 {
        char src[VM_TEMPSTRING_MAXSIZE];
        char destbuf[VM_TEMPSTRING_MAXSIZE];
+       size_t destbuf_len;
        int pad;
+
        VM_SAFEPARMCOUNTRANGE(1, 8, VM_strpad);
        pad = (int) PRVM_G_FLOAT(OFS_PARM0);
        VM_VarString(prog, 1, src, sizeof(src));
 
        // note: < 0 = left padding, > 0 = right padding,
        // this is reverse logic of printf!
-       dpsnprintf(destbuf, sizeof(destbuf), "%*s", -pad, src);
+       destbuf_len = dpsnprintf(destbuf, sizeof(destbuf), "%*s", -pad, src);
 
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, destbuf);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, destbuf, destbuf_len);
 }
 
 // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
@@ -5081,7 +5119,7 @@ void VM_infoadd (prvm_prog_t *prog)
 
        InfoString_SetValue(temp, VM_TEMPSTRING_MAXSIZE, key, value);
 
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, temp);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, temp, strlen(temp));
 }
 
 // #227 string(string info, string key) infoget (FTE_STRINGS)
@@ -5098,7 +5136,7 @@ void VM_infoget (prvm_prog_t *prog)
 
        InfoString_GetValue(info, key, value, VM_TEMPSTRING_MAXSIZE);
 
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, value);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, value, strlen(value));
 }
 
 //#228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
@@ -5191,8 +5229,8 @@ void VM_digest_hex(prvm_prog_t *prog)
                        outhex[2*i]   = hexmap[(out[i] >> 4) & 15];
                        outhex[2*i+1] = hexmap[(out[i] >> 0) & 15];
                }
-               outhex[2*i] = 0;
-               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, outhex);
+               outhex[2*i] = '\0';
+               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, outhex, 2*i);
        }
        else
                PRVM_G_INT(OFS_RETURN) = 0;
@@ -5218,7 +5256,7 @@ void VM_SetTraceGlobals(prvm_prog_t *prog, const trace_t *trace)
        PRVM_gameglobalfloat(trace_dpstartcontents) = trace->startsupercontents;
        PRVM_gameglobalfloat(trace_dphitcontents) = trace->hitsupercontents;
        PRVM_gameglobalfloat(trace_dphitq3surfaceflags) = trace->hitq3surfaceflags;
-       PRVM_gameglobalstring(trace_dphittexturename) = trace->hittexture ? PRVM_SetTempString(prog, trace->hittexture->name) : 0;
+       PRVM_gameglobalstring(trace_dphittexturename) = trace->hittexture ? PRVM_SetTempString(prog, trace->hittexture->name, strlen(trace->hittexture->name)) : 0;
 }
 
 void VM_ClearTraceGlobals(prvm_prog_t *prog)
@@ -5286,9 +5324,9 @@ void VM_uri_escape (prvm_prog_t *prog)
                        *q++ = hex[ *(unsigned char *)p       & 0xF];
                }
        }
-       *q++ = 0;
+       *q = '\0';
 
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, dest);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, dest, q - dest);
 }
 
 // #510 string(string input, ...) uri_unescape (DP_QC_URI_ESCAPE)
@@ -5333,9 +5371,9 @@ nohex:
                // otherwise:
                *q++ = *p++;
        }
-       *q++ = 0;
+       *q = '\0';
 
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, dest);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, dest, q - dest);
 }
 
 // #502 string(string filename) whichpack (DP_QC_WHICHPACK)
@@ -5348,7 +5386,7 @@ void VM_whichpack (prvm_prog_t *prog)
        fn = PRVM_G_STRING(OFS_PARM0);
        pack = FS_WhichPack(fn);
 
-       PRVM_G_INT(OFS_RETURN) = pack ? PRVM_SetTempString(prog, pack) : 0;
+       PRVM_G_INT(OFS_RETURN) = pack ? PRVM_SetTempString(prog, pack, strlen(pack)) : 0;
 }
 
 typedef struct
@@ -5386,11 +5424,11 @@ static void uri_to_string_callback(int status, size_t length_received, unsigned
        {
                if(length_received >= sizeof(handle->buffer))
                        length_received = sizeof(handle->buffer) - 1;
-               handle->buffer[length_received] = 0;
+               handle->buffer[length_received] = '\0';
 
                PRVM_G_FLOAT(OFS_PARM0) = handle->id;
                PRVM_G_FLOAT(OFS_PARM1) = status;
-               PRVM_G_INT(OFS_PARM2) = PRVM_SetTempString(prog, handle->buffer);
+               PRVM_G_INT(OFS_PARM2) = PRVM_SetTempString(prog, handle->buffer, length_received);
                prog->ExecuteProgram(prog, PRVM_allfunction(URI_Get_Callback), "QC function URI_Get_Callback is missing");
        }
 
@@ -5570,6 +5608,7 @@ void VM_netaddress_resolve (prvm_prog_t *prog)
 {
        const char *ip;
        char normalized[128];
+       size_t normalized_len;
        int port;
        lhnetaddress_t addr;
 
@@ -5580,10 +5619,10 @@ void VM_netaddress_resolve (prvm_prog_t *prog)
        if(prog->argc > 1)
                port = (int) PRVM_G_FLOAT(OFS_PARM1);
 
-       if(LHNETADDRESS_FromString(&addr, ip, port) && LHNETADDRESS_ToString(&addr, normalized, sizeof(normalized), prog->argc > 1))
-               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, normalized);
+       if(LHNETADDRESS_FromString(&addr, ip, port) && (normalized_len = LHNETADDRESS_ToString(&addr, normalized, sizeof(normalized), prog->argc > 1)))
+               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, normalized, normalized_len);
        else
-               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, "");
+               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, "", 0);
 }
 
 //string(prvm_prog_t *prog) getextresponse = #624; // returns the next extResponse packet that was sent to this client
@@ -5598,7 +5637,7 @@ void VM_CL_getextresponse (prvm_prog_t *prog)
                int first;
                --cl_net_extresponse_count;
                first = (cl_net_extresponse_last + NET_EXTRESPONSE_MAX - cl_net_extresponse_count) % NET_EXTRESPONSE_MAX;
-               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, cl_net_extresponse[first]);
+               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, cl_net_extresponse[first], strlen(cl_net_extresponse[first]));
        }
 }
 
@@ -5613,7 +5652,7 @@ void VM_SV_getextresponse (prvm_prog_t *prog)
                int first;
                --sv_net_extresponse_count;
                first = (sv_net_extresponse_last + NET_EXTRESPONSE_MAX - sv_net_extresponse_count) % NET_EXTRESPONSE_MAX;
-               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, sv_net_extresponse[first]);
+               PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, sv_net_extresponse[first], strlen(sv_net_extresponse[first]));
        }
 }
 
@@ -6066,9 +6105,10 @@ verbatim:
                                break;
                }
        }
+
 finished:
-       *o = 0;
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, outbuf);
+       *o = '\0';
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, outbuf, o - outbuf);
 }
 
 
@@ -6394,11 +6434,12 @@ void VM_getsurfacetexture(prvm_prog_t *prog)
 {
        model_t *model;
        msurface_t *surface;
+
        VM_SAFEPARMCOUNT(2, VM_getsurfacetexture);
        PRVM_G_INT(OFS_RETURN) = OFS_NULL;
        if (!(model = getmodel(prog, PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
                return;
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, surface->texture->name);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, surface->texture->name, strlen(surface->texture->name));
 }
 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
 void VM_getsurfacenearpoint(prvm_prog_t *prog)
index 46bab5d2f92a710248f8629a3e7cf85c52c2dc5b..24fe4a91b1f7b589aa6ffbcf041a40d32f0da9a6 100644 (file)
@@ -218,7 +218,7 @@ float       getserverlistindexforkey(string key)
 void VM_CheckEmptyString (prvm_prog_t *prog, const char *s);
 /// Returns the length of the *out string excluding the \0 terminator.
 size_t VM_VarString(prvm_prog_t *prog, int first, char *out, size_t outsize);
-qbool PRVM_ConsoleCommand (prvm_prog_t *prog, const char *text, int *func, qbool preserve_self, int curself, double ptime, qbool prog_loaded, const char *error_message);
+qbool PRVM_ConsoleCommand(prvm_prog_t *prog, const char *text, size_t textlen, int *func, qbool preserve_self, int curself, double ptime, qbool prog_loaded, const char *error_message);
 prvm_stringbuffer_t *BufStr_FindCreateReplace (prvm_prog_t *prog, int bufindex, int flags, const char *format);
 void BufStr_Set(prvm_prog_t *prog, prvm_stringbuffer_t *stringbuffer, int strindex, const char *str);
 void BufStr_Del(prvm_prog_t *prog, prvm_stringbuffer_t *stringbuffer);
index 36a44e481266c9dfb51fc5eba9cbe9ae3d15a0ca..aa05028fc13c7d43dea99c3bce30f80ebe2c9c91 100644 (file)
@@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "quakedef.h"
 #include "progsvm.h"
 #include "csprogs.h"
+#include "prvm_cmds.h"
 
 prvm_prog_t prvm_prog_list[PRVM_PROG_MAX];
 
@@ -1123,7 +1124,7 @@ static void PRVM_GameCommand(cmd_state_t *cmd, const char *whichprogs, const cha
                s = Cmd_Args(cmd);
 
                restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize;
-               PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(prog, s ? s : "");
+               PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(prog, s ? s : "", s ? strlen(s) : 0);
                prog->ExecuteProgram(prog, PRVM_allfunction(GameCommand), "QC function GameCommand is missing");
                prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
        }
@@ -3366,23 +3367,23 @@ int PRVM_SetEngineString(prvm_prog_t *prog, const char *s)
 //  restores it on return, so multiple recursive calls can share the same
 //  buffer)
 // the buffer size is automatically grown as needed
-
-int PRVM_SetTempString(prvm_prog_t *prog, const char *s)
+int PRVM_SetTempString(prvm_prog_t *prog, const char *s, size_t slen)
 {
-       int size;
+       size_t size;
        char *t;
-       if (!s)
+
+       if (!s || slen >= VM_TEMPSTRING_MAXSIZE)
                return 0;
-       size = (int)strlen(s) + 1;
+       size = slen + 1;
        if (developer_insane.integer)
-               Con_DPrintf("PRVM_SetTempString %s: cursize %i, size %i\n", prog->name, prog->tempstringsbuf.cursize, size);
-       if (prog->tempstringsbuf.maxsize < prog->tempstringsbuf.cursize + size)
+               Con_DPrintf("PRVM_SetTempString %s: cursize %i, size %zu\n", prog->name, prog->tempstringsbuf.cursize, size);
+       if ((size_t)prog->tempstringsbuf.maxsize < prog->tempstringsbuf.cursize + size)
        {
                sizebuf_t old = prog->tempstringsbuf;
                if (prog->tempstringsbuf.cursize + size >= 1<<28)
-                       prog->error_cmd("PRVM_SetTempString %s: ran out of tempstring memory!  (refusing to grow tempstring buffer over 256MB, cursize %i, size %i)\n", prog->name, prog->tempstringsbuf.cursize, size);
+                       prog->error_cmd("PRVM_SetTempString %s: ran out of tempstring memory!  (refusing to grow tempstring buffer over 256MB, cursize %i, size %zu)\n", prog->name, prog->tempstringsbuf.cursize, size);
                prog->tempstringsbuf.maxsize = max(prog->tempstringsbuf.maxsize, 65536);
-               while (prog->tempstringsbuf.maxsize < prog->tempstringsbuf.cursize + size)
+               while ((size_t)prog->tempstringsbuf.maxsize < prog->tempstringsbuf.cursize + size)
                        prog->tempstringsbuf.maxsize *= 2;
                if (prog->tempstringsbuf.maxsize != old.maxsize || prog->tempstringsbuf.data == NULL)
                {
index 729418d9410a152713eac3f3d9c5b67f9b244a0d..22b6a1f84f686e78320f11f99f5b996b70d715e5 100644 (file)
--- a/server.h
+++ b/server.h
@@ -625,6 +625,6 @@ void SV_PreSpawn_f(cmd_state_t *cmd);
 void SV_Spawn_f(cmd_state_t *cmd);
 void SV_Begin_f(cmd_state_t *cmd);
 
-qbool SV_VM_ConsoleCommand (const char *text);
+qbool SV_VM_ConsoleCommand(const char *text, size_t textlen);
 
 #endif
index 6a621bac6d293c9ec2a573187e7ee821f1f805c9..58bef9bfb0a3f44a31ac9ec3270af7a91c19f75a 100644 (file)
--- a/sv_user.c
+++ b/sv_user.c
@@ -987,6 +987,7 @@ void SV_ReadClientMessage(void)
        prvm_prog_t *prog = SVVM_prog;
        int netcmd, num, start;
        char *s, *p, *q;
+       size_t slen;
 
        if(sv_autodemo_perclient.integer >= 2)
                SV_WriteDemoMessage(host_client, &(host_client->netconnection->message), true);
@@ -1035,7 +1036,8 @@ void SV_ReadClientMessage(void)
                        // allow reliable messages now as the client is done with initial loading
                        if (host_client->sendsignon == 2)
                                host_client->sendsignon = 0;
-                       s = MSG_ReadString(&sv_message, sv_readstring, sizeof(sv_readstring));
+                       slen = MSG_ReadString_len(&sv_message, sv_readstring, sizeof(sv_readstring));
+                       s = sv_readstring;
                        q = NULL;
                        for(p = s; *p; ++p) switch(*p)
                        {
@@ -1054,19 +1056,19 @@ void SV_ReadClientMessage(void)
                        if (strncasecmp(s, "spawn", 5) == 0
                         || strncasecmp(s, "begin", 5) == 0
                         || strncasecmp(s, "prespawn", 8) == 0)
-                               Cmd_ExecuteString (cmd_serverfromclient, s, src_client, true);
+                               Cmd_ExecuteString(cmd_serverfromclient, s, slen, src_client, true);
                        else if (PRVM_serverfunction(SV_ParseClientCommand))
                        {
                                int restorevm_tempstringsbuf_cursize;
                                restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize;
-                               PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(prog, s);
+                               PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(prog, s, slen);
                                PRVM_serverglobalfloat(time) = sv.time;
                                PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(host_client->edict);
                                prog->ExecuteProgram(prog, PRVM_serverfunction(SV_ParseClientCommand), "QC function SV_ParseClientCommand is missing");
                                prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
                        }
                        else
-                               Cmd_ExecuteString (cmd_serverfromclient, s, src_client, true);
+                               Cmd_ExecuteString(cmd_serverfromclient, s, slen, src_client, true);
                        break;
 
 clc_stringcmd_invalid:
index 3f595f218d729111db453f2a21e26df3a7f0885d..278786ea481c47a3f10c82fb388896ca444f0635 100644 (file)
@@ -2433,7 +2433,7 @@ static void VM_SV_clientcommand(prvm_prog_t *prog)
 
        temp_client = host_client;
        host_client = svs.clients + i;
-       Cmd_ExecuteString(cmd_serverfromclient, PRVM_G_STRING(OFS_PARM1), src_client, true);
+       Cmd_ExecuteString(cmd_serverfromclient, PRVM_G_STRING(OFS_PARM1), strlen(PRVM_G_STRING(OFS_PARM1)), src_client, true);
        host_client = temp_client;
 }
 
@@ -2686,7 +2686,7 @@ static void VM_SV_gettaginfo(prvm_prog_t *prog)
        Matrix4x4_ToVectors(&tag_localmatrix, forward, left, up, origin);
 
        PRVM_serverglobalfloat(gettaginfo_parent) = parentindex;
-       PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname) : 0;
+       PRVM_serverglobalstring(gettaginfo_name) = tagname ? PRVM_SetTempString(prog, tagname, strlen(tagname)) : 0;
        VectorCopy(forward, PRVM_serverglobalvector(gettaginfo_forward));
        VectorNegate(left, PRVM_serverglobalvector(gettaginfo_right));
        VectorCopy(up, PRVM_serverglobalvector(gettaginfo_up));
@@ -2785,9 +2785,10 @@ string(string key) serverkey
 static void VM_SV_serverkey(prvm_prog_t *prog)
 {
        char string[VM_TEMPSTRING_MAXSIZE];
+
        VM_SAFEPARMCOUNT(1, VM_SV_serverkey);
        InfoString_GetValue(svs.serverinfo, PRVM_G_STRING(OFS_PARM0), string, sizeof(string));
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, string, strlen(string));
 }
 
 //#333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC)
@@ -2924,10 +2925,10 @@ static void VM_SV_pointparticles(prvm_prog_t *prog)
        SV_FlushBroadcastMessages();
 }
 
-qbool SV_VM_ConsoleCommand (const char *text)
+qbool SV_VM_ConsoleCommand(const char *text, size_t textlen)
 {
        prvm_prog_t *prog = SVVM_prog;
-       return PRVM_ConsoleCommand(prog, text, &prog->funcoffsets.ConsoleCmd, true, PRVM_EDICT_TO_PROG(sv.world.prog->edicts), sv.time,  !(!sv.active || !prog || !prog->loaded), "QC function ConsoleCmd is missing"); 
+       return PRVM_ConsoleCommand(prog, text, textlen, &prog->funcoffsets.ConsoleCmd, true, PRVM_EDICT_TO_PROG(sv.world.prog->edicts), sv.time,  !(!sv.active || !prog || !prog->loaded), "QC function ConsoleCmd is missing");
 }
 
 // #352 void(string cmdname) registercommand (EXT_CSQC)
@@ -3043,7 +3044,7 @@ static void VM_SV_skel_get_bonename(prvm_prog_t *prog)
                return;
        if (bonenum < 0 || bonenum >= skeleton->model->num_bones)
                return;
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, skeleton->model->data_bones[bonenum].name, strlen(skeleton->model->data_bones[bonenum].name));
 }
 
 // #267 float(float skel, float bonenum) skel_get_boneparent = #267; // (FTE_CSQC_SKELETONOBJECTS) returns parent num for supplied bonenum, 0 if bonenum has no parent or bone does not exist (returned value is always less than bonenum, you can loop on this)