java-topology/whitepaper/outreach/xash3d-0002.md
russell@unturf.com 6784cdf1cf feat: add 39 outreach docs (batches 6-8)
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.
2026-04-14 17:06:28 -04:00

2.9 KiB
Raw Blame History

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.

  1. Confirm receipt and assign a GitHub issue reference (FWGS/xash3d-fwgs).
  2. Assess severity — fires on every map load across four resource types, quadratic in precache count.
  3. Coordinate a disclosure date — we target 90 days from first contact.
  4. 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.