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.9 KiB
Xash3D FWGS — CWE-407 Disclosure Brief (xash3d-0002)
2026-04-13 · Patch available — awaiting upstream merge
Finding
Four O(N²) defects in Xash3D server resource precaching. SV_ModelIndex, SV_SoundIndex, SV_EventIndex, and SV_GenericIndex each perform a linear scan of their respective precache arrays on every registration call, producing O(N²/2) total comparisons per resource type during map load.
The Defects
xash3d-0002 (PATCHED — MEDIUM): engine/server/sv_init.c
// SV_ModelIndex — called N times during map load:
for( i = 1; i < MAX_MODELS && sv.model_precache[i][0]; i++ )
{
if( !Q_stricmp( sv.model_precache[i], name ))
return i;
}
The same linear scan pattern repeats in SV_SoundIndex (MAX_SOUNDS=2048), SV_EventIndex (MAX_EVENTS), and SV_GenericIndex (MAX_CUSTOM). Each precache call scans all previously registered entries via Q_stricmp. Registering N resources costs O(1+2+...+N) = O(N²/2).
Complexity Proof
At N=1000 precached models (MAX_MODELS=4096):
- Defective: 1000 × 500 average = 500,000 case-insensitive string comparisons
- Fixed: 1000 × O(1) hash lookups = 1,000 operations
- ~500x op reduction per resource type per map load.
Multiplied across 4 resource types (models, sounds, events, generics), heavy mods accumulate millions of unnecessary comparisons.
Impact
Xash3D FWGS serves the Half-Life 1 modding community. Mods like Sven Co-op push precache limits with thousands of custom models and sounds. Every map load, every server restart, and every level transition pays quadratic cost in string comparisons. Dedicated servers running map rotations compound this overhead continuously.
The Fix
Add parallel hash tables (one per resource type) for O(1) amortized dedup, mirroring the SV_BuildConsistencyHash pattern from xash3d-0001:
// Before (O(N) scan per call)
for( i = 1; i < MAX_MODELS && sv.model_precache[i][0]; i++ )
if( !Q_stricmp( sv.model_precache[i], name )) return i;
// After (O(1) hash lookup)
// CWE-407 fix: hash table alongside precache array.
h = COM_HashKey( name, PRECACHE_HASH_SIZE );
for( e = model_hash[h]; e; e = e->next )
if( !Q_stricmp( sv.model_precache[e->index], name )) return e->index;
Patch
Fix available: defects/xash3d-0002/patch/xash3d-0002.patch
Single-file patch on engine/server/sv_init.c. Adds defect annotations to all four precache functions. Hash table implementation mirrors xash3d-0001 pattern.
What We Ask
A patch is ready for review.
- Confirm receipt and assign a GitHub issue reference (FWGS/xash3d-fwgs).
- Assess severity — fires on every map load across four resource types, quadratic in precache count.
- Coordinate a disclosure date — we target 90 days from first contact.
- We will credit the Xash3D FWGS team in the public disclosure. Preferred acknowledgment format welcome.
Contact: see cover email. This brief is confidential until coordinated disclosure.