Batch 6 (9): dolibarr, jitsi-videobridge, zed, tryton, suricata, strawberry, zulip, zesarux, zephyr Batch 7 (15): xonotic (4), xash3d (3), xenia, xtuple, zabbix (2), zathura, zebra, yabause, zephyr-0001 Batch 8 (15): woodpecker (2), wine (4), widelands (3), wesnoth (3), wekan (3) Mix of CWE-407 and CWE-312.
2.6 KiB
Xonotic (DarkPlaces) — CWE-407 Disclosure Brief (xonotic-0004)
2026-04-13 · Patch available — awaiting upstream merge
Finding
One O(N²) defect in DarkPlaces sound name lookup. S_FindName traverses a linked list of all known sound effects on every sound reference, making each lookup O(N) where N = total loaded sounds. The existing code contains a TODO comment: "TODO: hash table search?".
The Defect
xonotic-0004 (PATCHED — MEDIUM): snd_main.c:922
// In S_FindName() — fires on every sound reference:
// TODO: hash table search?
for (sfx = known_sfx; sfx != NULL; sfx = sfx->next)
if(!strcmp (sfx->name, name))
return sfx;
known_sfx is a singly-linked list of all loaded sfx_t entries. Every sound playback, precache, or reference calls S_FindName, which walks the entire list via strcmp. As the game loads more sounds, every subsequent lookup grows linearly.
Complexity Proof
At N=300 loaded sounds, L=1000 lookups per map load:
- Defective: 1000 × 150 average = 150,000 string comparisons
- Fixed: 1000 × O(1) hash lookups = 1,000 operations
- ~150x op reduction.
Impact
DarkPlaces loads sounds throughout gameplay (not just at map load). Every weapon fire, footstep, and ambient trigger calls S_FindName. Games with large sound libraries (Xonotic ships with hundreds of sound files) pay this cost on every audio event. The engine developers themselves identified this as a candidate for optimization (the TODO comment).
The Fix
Add a hash table (sfx_hashtable[256]) with per-sfx chain pointers for O(1) average lookup:
// Before
// TODO: hash table search?
for (sfx = known_sfx; sfx != NULL; sfx = sfx->next)
if(!strcmp(sfx->name, name)) return sfx;
// After
// CWE-407 fix: hash table replaces O(N) linked list scan.
unsigned hashkey = S_NameHash(name);
for (sfx = sfx_hashtable[hashkey]; sfx != NULL; sfx = sfx->hashnext)
if (!strcmp(sfx->name, name)) return sfx;
Patch
Fix available: defects/xonotic-0004/patch/xonotic-0004.patch
Two-file patch across snd_main.c and snd_main.h. Adds hashnext pointer to sfx_t struct, hash table array, and hash function.
What We Ask
A patch is ready for review.
- Confirm receipt and assign a GitHub issue reference (xonotic/darkplaces).
- Assess severity — fires on every sound playback event, scaling with loaded sound count.
- Coordinate a disclosure date — we target 90 days from first contact.
- We will credit the Xonotic/DarkPlaces team in the public disclosure. Preferred acknowledgment format welcome.
Contact: see cover email. This brief is confidential until coordinated disclosure.