diff --git a/rehlds/engine/common.cpp b/rehlds/engine/common.cpp index c9f07a6..fa1facb 100644 --- a/rehlds/engine/common.cpp +++ b/rehlds/engine/common.cpp @@ -1446,31 +1446,64 @@ char *COM_FileExtension(char *in) #endif // #ifdef REHLDS_FIXES } -// Fills "out" with the file name without path and extension. +// Fills "out" with the file name without path and extension void COM_FileBase(const char *in, char *out) { - const char *start, *end; - int len; + COM_FileBase_s(in, out, -1); +} - *out = 0; - - len = Q_strlen(in); - if (len <= 0) - return; - - start = in + len - 1; - end = in + len; - while (start >= in && *start != '/' && *start != '\\') +// Extracts the base name of a file (no path, no extension, assumes '/' as path separator) +const char *COM_FileBase_s(const char *in, char *out, int size) +{ + if (!in || !in[0]) { - if (*start == '.') - end = start; - start--; + *out = '\0'; + return NULL; } - start++; - len = end - start; - Q_strncpy(out, start, len); - out[len] = 0; + int len = Q_strlen(in); + if (len <= 0) + return NULL; + + // scan backward for '.' + int end = len - 1; + while (end && in[end] != '.' && !PATHSEPARATOR(in[end])) + end--; + + // no '.', copy to end + if (in[end] != '.') + { + end = len - 1; + } + else + { + // Found ',', copy to left of '.' + end--; + } + + // Scan backward for '/' + int start = len - 1; + while (start >= 0 && !PATHSEPARATOR(in[start])) + start--; + + if (start < 0 || !PATHSEPARATOR(in[start])) + { + start = 0; + } + else + { + start++; + } + + // Length of new sting + int maxcopy = end - start + 1; + if (size >= 0 && maxcopy >= size) + return NULL; + + // Copy partial string + Q_strncpy(out, &in[start], maxcopy); + out[maxcopy] = '\0'; + return out; } void COM_DefaultExtension(char *path, char *extension) @@ -1962,7 +1995,7 @@ int EXT_FUNC COM_FileSize(const char *filename) unsigned char* EXT_FUNC COM_LoadFile(const char *path, int usehunk, int *pLength) { - char base[33]; + char base[MAX_PATH]; unsigned char *buf = NULL; #ifndef SWDS @@ -1982,8 +2015,10 @@ unsigned char* EXT_FUNC COM_LoadFile(const char *path, int usehunk, int *pLength } int len = FS_Size(hFile); - COM_FileBase(path, base); - base[32] = 0; + if (!COM_FileBase_s(path, base, sizeof(base))) + Sys_Error("%s: Bad path length: %s", __func__, path); + + base[32] = '\0'; switch (usehunk) { diff --git a/rehlds/engine/common.h b/rehlds/engine/common.h index 22d07e9..1a7fc08 100644 --- a/rehlds/engine/common.h +++ b/rehlds/engine/common.h @@ -169,6 +169,7 @@ NOXREF char *COM_SkipPath(char *pathname); void COM_StripExtension(char *in, char *out); char *COM_FileExtension(char *in); void COM_FileBase(const char *in, char *out); +const char *COM_FileBase_s(const char *in, char *out, int size); void COM_DefaultExtension(char *path, char *extension); void COM_UngetToken(void); char *COM_Parse(char *data); diff --git a/rehlds/engine/model.cpp b/rehlds/engine/model.cpp index a4581e5..12bd90f 100644 --- a/rehlds/engine/model.cpp +++ b/rehlds/engine/model.cpp @@ -29,7 +29,7 @@ #include "precompiled.h" model_t *loadmodel; -char loadname[32]; +char loadname[MAX_MODEL_NAME]; model_t mod_known[MAX_KNOWN_MODELS]; int mod_numknown; unsigned char* mod_base; @@ -330,7 +330,12 @@ model_t *Mod_LoadModel(model_t *mod, qboolean crash, qboolean trackCRC) Con_DPrintf("loading %s\n", mod->name); // allocate a new model - COM_FileBase(mod->name, loadname); + if (!COM_FileBase_s(mod->name, loadname, sizeof(loadname))) + { + Sys_Error("%s: Bad model name length: %s", __func__, mod->name); + return NULL; + } + loadmodel = mod; mod->needload = NL_PRESENT; diff --git a/rehlds/engine/model_rehlds.h b/rehlds/engine/model_rehlds.h index f360181..61906f0 100644 --- a/rehlds/engine/model_rehlds.h +++ b/rehlds/engine/model_rehlds.h @@ -46,7 +46,7 @@ #include "crc.h" extern model_t* loadmodel; -extern char loadname[32]; +extern char loadname[MAX_MODEL_NAME]; extern model_t mod_known[MAX_KNOWN_MODELS]; extern int mod_numknown; extern unsigned char* mod_base;