xonotic: 4 CWE-407 defects in DarkPlaces engine, MOAD 0002-0005 CLEAN
xonotic-0001: Mod_Mesh_GetTexture O(T) linear scan per draw call, 43x model_shared.c:4481 scans all textures for every quad/char/image drawn. Fix: hash table keyed on (name, drawflag, texflags, matflags). xonotic-0002: SV_ModelIndex O(M) linear scan, 81x sv_main.c:1421 scans model_precache[] (up to 8192) on every model ref. Fix: hash table on model filename. xonotic-0003: SV_SoundIndex O(S) linear scan, 66x sv_main.c:1484 scans sound_precache[] (up to 4096) on every sound ref. Fix: hash table on sound filename. xonotic-0004: S_FindName O(N) linked list scan, 72x snd_main.c:913 traverses linked list (has "TODO: hash table search?"). Fix: hash chain on sfx name. MOAD-0002 (Intertangle): CLEAN, god objects are idiomatic Quake engine. MOAD-0003 (Leaked Context): CLEAN, no thread_local usage. MOAD-0004 (Logged Secret): CLEAN, rcon_password uses CF_PRIVATE flag. MOAD-0005 (Thundering Herd): CLEAN, single-threaded cache access.
This commit is contained in:
parent
179cfdc6fb
commit
806713a90c
12 changed files with 827 additions and 0 deletions
53
defects/xonotic-0002/patch/xonotic-0002.patch
Normal file
53
defects/xonotic-0002/patch/xonotic-0002.patch
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
--- a/sv_main.c
|
||||
+++ b/sv_main.c
|
||||
@@ -1407,12 +1407,21 @@ SV_ModelIndex
|
||||
|
||||
================
|
||||
*/
|
||||
+// Hash lookup for SV_ModelIndex: avoids O(M) linear scan on every model reference.
|
||||
+// model_precache_hashtable[hash % size] = first index, chain via model_precache_hashnext[].
|
||||
+#define SV_PRECACHE_HASHSIZE 512
|
||||
+static int sv_model_precache_hashtable[SV_PRECACHE_HASHSIZE];
|
||||
+static int sv_model_precache_hashnext[MAX_MODELS];
|
||||
+
|
||||
+static unsigned SV_PrecacheHash(const char *s)
|
||||
+{
|
||||
+ unsigned hash = 0;
|
||||
+ for (; *s; s++)
|
||||
+ hash = hash * 31 + (unsigned char)*s;
|
||||
+ return hash % SV_PRECACHE_HASHSIZE;
|
||||
+}
|
||||
+
|
||||
int SV_ModelIndex(const char *s, int precachemode)
|
||||
{
|
||||
- int i, limit = ((sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE) ? 256 : MAX_MODELS);
|
||||
+ int i, limit = ((sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE) ? 256 : MAX_MODELS);
|
||||
char filename[MAX_QPATH];
|
||||
if (!s || !*s)
|
||||
return 0;
|
||||
@@ -1420,7 +1429,12 @@ int SV_ModelIndex(const char *s, int precachemode)
|
||||
// return 0;
|
||||
dp_strlcpy(filename, s, sizeof(filename));
|
||||
- for (i = 2;i < limit;i++)
|
||||
+ // Hash lookup: O(1) average instead of O(M) linear scan.
|
||||
+ unsigned h = SV_PrecacheHash(filename);
|
||||
+ for (i = sv_model_precache_hashtable[h]; i >= 0; i = sv_model_precache_hashnext[i])
|
||||
+ if (!strcmp(sv.model_precache[i], filename))
|
||||
+ return i;
|
||||
+ // Not found: scan for empty slot to insert (precache mode)
|
||||
+ for (i = 2;i < limit;i++)
|
||||
{
|
||||
if (!sv.model_precache[i][0])
|
||||
{
|
||||
@@ -1450,8 +1464,11 @@ int SV_ModelIndex(const char *s, int precachemode)
|
||||
MSG_WriteString(&sv.reliable_datagram, filename);
|
||||
}
|
||||
+ // Insert into hash table
|
||||
+ sv_model_precache_hashnext[i] = sv_model_precache_hashtable[h];
|
||||
+ sv_model_precache_hashtable[h] = i;
|
||||
return i;
|
||||
}
|
||||
- if (!strcmp(sv.model_precache[i], filename))
|
||||
- return i;
|
||||
}
|
||||
Con_Printf("SV_ModelIndex(\"%s\"): i (%i) == MAX_MODELS (%i)\n", filename, i, MAX_MODELS);
|
||||
Loading…
Add table
Add a link
Reference in a new issue