From 5f3573143a574d188b8f4736101ffc8071cb23c4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 8 May 2003 23:24:02 +0000 Subject: [PATCH] the beginnings of a jihad against buffer overflows --- libs/audio/cd/cd_sgi.c | 2 +- libs/audio/renderer/snd_dma.c | 29 ++++++++++--------------- libs/console/client.c | 3 ++- libs/console/filelist.c | 2 +- libs/gamecode/engine/pr_load.c | 7 +++--- libs/gamecode/engine/pr_parse.c | 34 +++++++++++++++++------------- libs/models/alias/gl_mesh.c | 22 ++++++++++++------- libs/models/alias/gl_model_alias.c | 12 ++--------- libs/models/brush/gl_model_brush.c | 21 ++++++++++-------- libs/net/nc/net_udp.c | 16 ++++++++------ libs/net/nc/net_udp6.c | 14 +++++++++--- libs/net/net_chan.c | 10 ++++++--- libs/util/cvar.c | 5 +---- libs/util/quakefs.c | 2 +- 14 files changed, 96 insertions(+), 83 deletions(-) diff --git a/libs/audio/cd/cd_sgi.c b/libs/audio/cd/cd_sgi.c index 75ad22689..950038ff0 100644 --- a/libs/audio/cd/cd_sgi.c +++ b/libs/audio/cd/cd_sgi.c @@ -61,7 +61,7 @@ static float cdvolume; static byte remap[100]; static byte playTrack; -static char cd_dev[64] = "/dev/cdrom"; +static char cd_dev[] = "/dev/cdrom"; static CDPLAYER *cdp = NULL; static cvar_t *bgmvolume; diff --git a/libs/audio/renderer/snd_dma.c b/libs/audio/renderer/snd_dma.c index 835718765..951179000 100644 --- a/libs/audio/renderer/snd_dma.c +++ b/libs/audio/renderer/snd_dma.c @@ -44,6 +44,7 @@ static __attribute__ ((unused)) const char rcsid[] = #include "QF/cmd.h" #include "QF/cvar.h" +#include "QF/dstring.h" #include "QF/model.h" #include "QF/qargs.h" #include "QF/sys.h" @@ -701,7 +702,7 @@ SND_ExtraUpdate (void) static void SND_Play (void) { - char name[256]; + dstring_t *name = dstring_new (); int i; static int hash = 345; sfx_t *sfx; @@ -709,25 +710,21 @@ SND_Play (void) i = 1; while (i < Cmd_Argc ()) { if (!strrchr (Cmd_Argv (i), '.')) { - if (strlen (Cmd_Argv (i)) + 4 >= MAX_QPATH) - Sys_Error ("Sound name too long: %s", Cmd_Argv (i)); - strcpy (name, Cmd_Argv (i)); - strncat (name, ".wav", sizeof (name) - strlen (name)); + dsprintf (name, "%s.wav", Cmd_Argv (i)); } else { - if (strlen (Cmd_Argv (i)) >= MAX_QPATH) - Sys_Error ("Sound name too long: %s", Cmd_Argv (i)); - strcpy (name, Cmd_Argv (i)); + dsprintf (name, "%s", Cmd_Argv (i)); } - sfx = SND_PrecacheSound (name); + sfx = SND_PrecacheSound (name->str); SND_StartSound (hash++, 0, sfx, listener_origin, 1.0, 1.0); i++; } + dstring_delete (name); } static void SND_PlayVol (void) { - char name[256]; + dstring_t *name = dstring_new (); float vol; int i; static int hash = 543; @@ -736,20 +733,16 @@ SND_PlayVol (void) i = 1; while (i < Cmd_Argc ()) { if (!strrchr (Cmd_Argv (i), '.')) { - if (strlen (Cmd_Argv (i)) + 4 >= MAX_QPATH) - Sys_Error ("Sound name too long: %s", Cmd_Argv (i)); - strcpy (name, Cmd_Argv (i)); - strncat (name, ".wav", sizeof (name) - strlen (name)); + dsprintf (name, "%s.wav", Cmd_Argv (i)); } else { - if (strlen (Cmd_Argv (i)) >= MAX_QPATH) - Sys_Error ("Sound name too long: %s", Cmd_Argv (i)); - strcpy (name, Cmd_Argv (i)); + dsprintf (name, "%s", Cmd_Argv (i)); } - sfx = SND_PrecacheSound (name); + sfx = SND_PrecacheSound (name->str); vol = atof (Cmd_Argv (i + 1)); SND_StartSound (hash++, 0, sfx, listener_origin, vol, 1.0); i += 2; } + dstring_delete (name); } static void diff --git a/libs/console/client.c b/libs/console/client.c index ce51ee198..fcf36de9f 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -737,7 +737,8 @@ C_NewMap (void) first_time = 0; Menu_Load (); } - strcpy (old_gamedir, qfs_gamedir->gamedir); + strncpy (old_gamedir, qfs_gamedir->gamedir, sizeof (old_gamedir)); + old_gamedir[sizeof (old_gamedir) - 1] = 0; } static void diff --git a/libs/console/filelist.c b/libs/console/filelist.c index 8086da0fe..fb0de3657 100644 --- a/libs/console/filelist.c +++ b/libs/console/filelist.c @@ -250,7 +250,7 @@ Con_Skyboxlist_f (void) for (i = 0; i < skyboxlist->count; i++) { if (strlen(skyboxlist->list[i]) > strlen(sb_endings[0]) && strcmp(skyboxlist->list[i] + strlen(skyboxlist->list[i]) - strlen(sb_endings[0]), sb_endings[0]) == 0) { strncpy(basename, skyboxlist->list[i], sizeof(basename)); - basename[strlen(skyboxlist->list[i]) - strlen(sb_endings[0])] = 0; + basename[sizeof(basename) - 1] = 0; c = 0; for (j = 1; sb_endings[j]; j++) { b = 0; diff --git a/libs/gamecode/engine/pr_load.c b/libs/gamecode/engine/pr_load.c index ba6712c3a..eb5b76994 100644 --- a/libs/gamecode/engine/pr_load.c +++ b/libs/gamecode/engine/pr_load.c @@ -43,6 +43,7 @@ static __attribute__ ((unused)) const char rcsid[] = #include "QF/cmd.h" #include "QF/crc.h" #include "QF/cvar.h" +#include "QF/dstring.h" #include "QF/hash.h" #include "QF/progs.h" #include "QF/qdefs.h" @@ -324,11 +325,11 @@ void PR_Error (progs_t *pr, const char *error, ...) { va_list argptr; - char string[1024]; + dstring_t *string = dstring_new (); va_start (argptr, error); - vsnprintf (string, sizeof (string), error, argptr); + dvsprintf (string, error, argptr); va_end (argptr); - Sys_Error ("%s: %s", pr->progs_name, string); + Sys_Error ("%s: %s", pr->progs_name, string->str); } diff --git a/libs/gamecode/engine/pr_parse.c b/libs/gamecode/engine/pr_parse.c index 6d5760cdd..b4965d2f2 100644 --- a/libs/gamecode/engine/pr_parse.c +++ b/libs/gamecode/engine/pr_parse.c @@ -227,7 +227,7 @@ static qboolean ED_ParseEpair (progs_t *pr, pr_type_t *base, ddef_t *key, const char *s) { int i; - char string[128]; + char *string; ddef_t *def; char *v, *w; pr_type_t *d; @@ -245,7 +245,7 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, ddef_t *key, const char *s) break; case ev_vector: - strcpy (string, s); + string = strdup (s); v = string; w = string; for (i = 0; i < 3; i++) { @@ -255,6 +255,7 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, ddef_t *key, const char *s) d->vector_var[i] = atof (w); w = v = v + 1; } + free (string); break; case ev_entity: @@ -298,7 +299,7 @@ ED_ParseEdict (progs_t *pr, const char *data, edict_t *ent) ddef_t *key; qboolean anglehack; qboolean init = false; - char keyname[256]; + dstring_t *keyname = dstring_new (); const char *token; int n; @@ -326,12 +327,12 @@ ED_ParseEdict (progs_t *pr, const char *data, edict_t *ent) if (!strcmp (token, "light")) token = "light_lev"; // hack for single light def - strcpy (keyname, token); + dstring_copystr (keyname, token); // another hack to fix heynames with trailing spaces - n = strlen (keyname); - while (n && keyname[n - 1] == ' ') { - keyname[n - 1] = 0; + n = strlen (keyname->str); + while (n && keyname->str[n - 1] == ' ') { + keyname->str[n - 1] = 0; n--; } @@ -347,13 +348,14 @@ ED_ParseEdict (progs_t *pr, const char *data, edict_t *ent) // keynames with a leading underscore are used for utility comments, // and are immediately discarded by quake - if (keyname[0] == '_') + if (keyname->str[0] == '_') continue; - key = ED_FindField (pr, keyname); + key = ED_FindField (pr, keyname->str); if (!key) { - if (!pr->parse_field || !pr->parse_field (pr, keyname, com_token)) { - Sys_Printf ("'%s' is not a field\n", keyname); + if (!pr->parse_field + || !pr->parse_field (pr, keyname->str, com_token)) { + Sys_Printf ("'%s' is not a field\n", keyname->str); continue; } } else { @@ -372,6 +374,7 @@ ED_ParseEdict (progs_t *pr, const char *data, edict_t *ent) if (!init) ent->free = true; + dstring_delete (keyname); return data; } @@ -381,7 +384,7 @@ ED_ParseEdict (progs_t *pr, const char *data, edict_t *ent) void ED_ParseGlobals (progs_t *pr, const char *data) { - char keyname[64]; + dstring_t *keyname = dstring_new (); ddef_t *key; while (1) { @@ -392,7 +395,7 @@ ED_ParseGlobals (progs_t *pr, const char *data) if (!data) PR_Error (pr, "ED_ParseEntity: EOF without closing brace"); - strcpy (keyname, com_token); + dstring_copystr (keyname, com_token); // parse value data = COM_Parse (data); @@ -402,15 +405,16 @@ ED_ParseGlobals (progs_t *pr, const char *data) if (com_token[0] == '}') PR_Error (pr, "ED_ParseEntity: closing brace without data"); - key = PR_FindGlobal (pr, keyname); + key = PR_FindGlobal (pr, keyname->str); if (!key) { - Sys_Printf ("'%s' is not a global\n", keyname); + Sys_Printf ("'%s' is not a global\n", keyname->str); continue; } if (!ED_ParseEpair (pr, pr->pr_globals, key, com_token)) PR_Error (pr, "ED_ParseGlobals: parse error"); } + dstring_delete (keyname); } diff --git a/libs/models/alias/gl_mesh.c b/libs/models/alias/gl_mesh.c index ed158b29c..cbc26078e 100644 --- a/libs/models/alias/gl_mesh.c +++ b/libs/models/alias/gl_mesh.c @@ -41,6 +41,7 @@ static __attribute__ ((unused)) const char rcsid[] = #include #include "QF/cvar.h" +#include "QF/dstring.h" #include "QF/mdfour.h" #include "QF/model.h" #include "QF/quakefs.h" @@ -336,7 +337,7 @@ BuildTris (void) void Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, int _s, int extra) { - char cache[MAX_QPATH], fullpath[MAX_OSPATH]; + dstring_t *cache, *fullpath; unsigned char model_digest[MDFOUR_DIGEST_BYTES]; unsigned char mesh_digest[MDFOUR_DIGEST_BYTES]; int i, j; @@ -348,6 +349,9 @@ Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, int _s, i aliasmodel = m; paliashdr = hdr; + cache = dstring_new (); + fullpath = dstring_new (); + if (!gl_alias_render_tri->int_val) { if (gl_mesh_cache->int_val @@ -357,12 +361,13 @@ Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, int _s, i mdfour (model_digest, (unsigned char *) _m, _s); // look for a cached version - strcpy (cache, "glquake/"); + dstring_copystr (cache, "glquake/"); + dstring_appendstr (cache, m->name); QFS_StripExtension (m->name + strlen ("progs/"), - cache + strlen ("glquake/")); - strncat (cache, ".qfms", sizeof (cache) - strlen (cache)); + cache->str + strlen ("glquake/")); + dstring_appendstr (cache, ".qfms"); - QFS_FOpenFile (cache, &f); + QFS_FOpenFile (cache->str, &f); if (f) { unsigned char d1[MDFOUR_DIGEST_BYTES]; unsigned char d2[MDFOUR_DIGEST_BYTES]; @@ -435,9 +440,8 @@ Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, int _s, i if (do_cache) { // save out the cached version - snprintf (fullpath, sizeof (fullpath), "%s/%s", - qfs_gamedir->dir.def, cache); - f = QFS_WOpen (fullpath, 9); + dsprintf (fullpath, "%s/%s", qfs_gamedir->dir.def, cache->str); + f = QFS_WOpen (fullpath->str, 9); if (f) { struct mdfour md; @@ -530,4 +534,6 @@ Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, int _s, i *verts++ = poseverts[i][vertexorder[j]]; } } + dstring_delete (cache); + dstring_delete (fullpath); } diff --git a/libs/models/alias/gl_model_alias.c b/libs/models/alias/gl_model_alias.c index 1fb675ace..7f1c0aa97 100644 --- a/libs/models/alias/gl_model_alias.c +++ b/libs/models/alias/gl_model_alias.c @@ -273,18 +273,10 @@ Mod_LoadExternalSkin (maliasskindesc_t *pskindesc, char *filename) QFS_FOpenFile (filename, &f); if (!f) { - char filename2[MAX_QPATH + 4]; - char *foo = filename2; - - foo = va ("progs/%s", filename); - QFS_FOpenFile (foo, &f); + QFS_FOpenFile (va ("progs/%s", filename), &f); } if (!f) { - char filename2[MAX_QPATH + 4]; - char *foo = filename2; - - foo = va ("textures/%s", filename); - QFS_FOpenFile (foo, &f); + QFS_FOpenFile (va ("textures/%s", filename), &f); } if (f) { targa = LoadTGA (f); diff --git a/libs/models/brush/gl_model_brush.c b/libs/models/brush/gl_model_brush.c index b81c4ccad..4d7ba9b27 100644 --- a/libs/models/brush/gl_model_brush.c +++ b/libs/models/brush/gl_model_brush.c @@ -42,6 +42,7 @@ static __attribute__ ((unused)) const char rcsid[] = #endif #include "QF/cvar.h" +#include "QF/dstring.h" #include "QF/model.h" #include "QF/qendian.h" #include "QF/quakefs.h" @@ -128,23 +129,22 @@ Mod_LoadLighting (lump_t *l) { byte d; byte *in, *out, *data; - char litfilename[1024]; + dstring_t *litfilename = dstring_new (); int i; loadmodel->lightdata = NULL; if (mod_lightmap_bytes > 1) { // LordHavoc: check for a .lit file to load - strcpy (litfilename, loadmodel->name); - QFS_StripExtension (litfilename, litfilename); - strncat (litfilename, ".lit", sizeof (litfilename) - - strlen (litfilename)); - data = (byte *) QFS_LoadHunkFile (litfilename); + dstring_copystr (litfilename, loadmodel->name); + QFS_StripExtension (litfilename->str, litfilename->str); + dstring_appendstr (litfilename, ".lit"); + data = (byte *) QFS_LoadHunkFile (litfilename->str); if (data) { if (data[0] == 'Q' && data[1] == 'L' && data[2] == 'I' && data[3] == 'T') { i = LittleLong (((int *) data)[1]); if (i == 1) { - Sys_DPrintf ("%s loaded", litfilename); + Sys_DPrintf ("%s loaded", litfilename->str); loadmodel->lightdata = data + 8; return; } else @@ -154,10 +154,12 @@ Mod_LoadLighting (lump_t *l) } } // LordHavoc: oh well, expand the white lighting data - if (!l->filelen) + if (!l->filelen) { + dstring_delete (litfilename); return; + } loadmodel->lightdata = Hunk_AllocName (l->filelen * mod_lightmap_bytes, - litfilename); + litfilename->str); in = mod_base + l->fileofs; out = loadmodel->lightdata; @@ -171,6 +173,7 @@ Mod_LoadLighting (lump_t *l) else for (i = 0; i < l->filelen ; i++) *out++ = gammatable[*in++]; + dstring_delete (litfilename); } msurface_t *warpface; diff --git a/libs/net/nc/net_udp.c b/libs/net/nc/net_udp.c index 8b957afcc..2f584aa31 100644 --- a/libs/net/nc/net_udp.c +++ b/libs/net/nc/net_udp.c @@ -70,6 +70,7 @@ static __attribute__ ((unused)) const char rcsid[] = #include "QF/console.h" #include "QF/cvar.h" +#include "QF/dstring.h" #include "QF/msg.h" #include "QF/sys.h" #include "QF/qargs.h" @@ -179,29 +180,32 @@ NET_BaseAdrToString (netadr_t a) qboolean NET_StringToAdr (const char *s, netadr_t *a) { - char copy[128]; + static dstring_t *copy; char *colon; struct hostent *h; struct sockaddr_in sadr; + if (!copy) + copy = dstring_new (); + memset (&sadr, 0, sizeof (sadr)); sadr.sin_family = AF_INET; sadr.sin_port = 0; - strcpy (copy, s); + dstring_copystr (copy, s); // strip off a trailing :port if present - for (colon = copy; *colon; colon++) + for (colon = copy->str; *colon; colon++) if (*colon == ':') { *colon = 0; sadr.sin_port = htons ((unsigned short) atoi (colon + 1)); } - if (copy[0] >= '0' && copy[0] <= '9') { - int addr = inet_addr (copy); + if (copy->str[0] >= '0' && copy->str[0] <= '9') { + int addr = inet_addr (copy->str); memcpy (&sadr.sin_addr, &addr, 4); } else { - if (!(h = gethostbyname (copy))) + if (!(h = gethostbyname (copy->str))) return 0; memcpy (&sadr.sin_addr, h->h_addr_list[0], 4); } diff --git a/libs/net/nc/net_udp6.c b/libs/net/nc/net_udp6.c index 223f9b556..06d69adf0 100644 --- a/libs/net/nc/net_udp6.c +++ b/libs/net/nc/net_udp6.c @@ -102,6 +102,7 @@ static __attribute__ ((unused)) const char rcsid[] = #undef model_t #include "QF/console.h" +#include "QF/dstring.h" #include "QF/msg.h" #include "QF/qargs.h" #include "QF/qtypes.h" @@ -246,7 +247,7 @@ NET_BaseAdrToString (netadr_t a) qboolean NET_StringToAdr (const char *s, netadr_t *a) { - char copy[128]; + static dstring_t *copy; char *addrs, *space; char *ports = NULL; int err; @@ -256,17 +257,21 @@ NET_StringToAdr (const char *s, netadr_t *a) struct sockaddr_in6 *ss6; struct sockaddr_in *ss4; + if (!copy) + copy = dstring_new (); + memset (&hints, 0, sizeof (hints)); hints.ai_socktype = SOCK_DGRAM; hints.ai_family = PF_UNSPEC; - strcpy (copy, s); - addrs = space = copy; + dstring_copystr (copy, s); + addrs = space = copy->str; if (*addrs == '[') { addrs++; for (; *space && *space != ']'; space++); if (!*space) { Con_Printf ("NET_StringToAdr: invalid IPv6 address %s\n", s); + dstring_delete (copy); return 0; } *space++ = '\0'; @@ -283,6 +288,7 @@ NET_StringToAdr (const char *s, netadr_t *a) // Error Con_Printf ("NET_StringToAdr: string %s:\n%s\n", s, gai_strerror (err)); + dstring_delete (copy); return 0; } @@ -308,10 +314,12 @@ NET_StringToAdr (const char *s, netadr_t *a) default: Con_Printf ("NET_StringToAdr: string %s:\nprotocol family %d not " "supported\n", s, resultp->ai_family); + dstring_delete (copy); return 0; } SockadrToNetadr ((struct sockaddr_in6 *) &ss, a); + dstring_delete (copy); return true; } diff --git a/libs/net/net_chan.c b/libs/net/net_chan.c index 4e222047f..3e1ac2a52 100644 --- a/libs/net/net_chan.c +++ b/libs/net/net_chan.c @@ -46,6 +46,7 @@ static __attribute__ ((unused)) const char rcsid[] = #include "QF/console.h" #include "QF/cvar.h" +#include "QF/dstring.h" #include "QF/msg.h" #include "QF/sys.h" @@ -169,14 +170,17 @@ Netchan_OutOfBand (netadr_t adr, int length, byte * data) void Netchan_OutOfBandPrint (netadr_t adr, const char *format, ...) { - static char string[8192]; // ?? why static? + static dstring_t *string; va_list argptr; + if (!string) + string = dstring_new (); + va_start (argptr, format); - vsnprintf (string, sizeof (string), format, argptr); + dvsprintf (string, format, argptr); va_end (argptr); - Netchan_OutOfBand (adr, strlen (string), (byte *) string); + Netchan_OutOfBand (adr, strlen (string->str), (byte *) string->str); } /* diff --git a/libs/util/cvar.c b/libs/util/cvar.c index 073f71a7f..bb540c543 100644 --- a/libs/util/cvar.c +++ b/libs/util/cvar.c @@ -285,10 +285,7 @@ Cvar_SetROM (cvar_t *var, const char *value) void Cvar_SetValue (cvar_t *var, float value) { - char val[32]; - - snprintf (val, sizeof (val), "%g", value); - Cvar_Set (var, val); + Cvar_Set (var, va ("%g", value)); } /* diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index 715929a4f..aafd62ed1 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -874,7 +874,7 @@ int loadsize; Filename are relative to the quake directory. Always appends a 0 byte to the loaded data. */ -byte * +byte * QFS_LoadFile (const char *path, int usehunk) { QFile *h;