Batch 9 (15): bun, bzflag (3), cake_wallet (4), calligra, caprice32 (2), cataclysm (3), cemu Batch 10 (15): cemu-0002, citra, clickhouse-java, cmake (3), cocos2d (3), conduit, cura (2), curaengine, clamav, contiki
2.9 KiB
BZFlag — CWE-407 Disclosure Brief (bzflag-0002)
2026-04-14 · Patch available — awaiting upstream merge
Finding
One O(n²) defect in BZFlag's access control list. The ban(), hostBan(), and idBan() methods use std::find on vectors for duplicate detection before insertion. When loading a master ban list via merge(), this makes ban list loading O(B²) where B = number of bans.
The Defect
bzflag-0002 (PATCHED — HIGH): src/bzfs/AccessControlList.cxx:41
// In AccessControlList::ban() — fires per ban during merge():
BanInfo toban(ipAddr, bannedBy, period, cidr, fromMaster);
banList_t::iterator oldit = std::find(banList.begin(), banList.end(), toban);
if (oldit != banList.end()) // O(B) linear scan for duplicate
*oldit = toban;
else
banList.push_back(toban);
The same pattern repeats in hostBan() and idBan(). When merge() processes every entry in a master ban list, each insertion scans the growing vector. Community servers with hundreds to thousands of bans pay quadratic cost on every ban list reload.
Complexity Proof
At B=1,000 bans:
- Defective: 1,000 insertions × average 500 comparisons = ~500,000 comparisons
- Fixed: 1,000 insertions × O(1) hash lookup = 1,000 lookups
- ~500× op reduction. Fires on server startup and ban list reload.
Impact
BZFlag community servers maintain shared master ban lists. Servers that pull from community ban databases with hundreds or thousands of entries pay quadratic cost on every startup and every periodic ban list refresh. Large community servers with active moderation accumulate thousands of bans over time.
The Fix
Add parallel std::unordered_set indexes for O(1) duplicate detection:
// Before
banList_t::iterator oldit = std::find(banList.begin(), banList.end(), toban);
// After
// CWE-407 fix: unordered_set index for O(1) duplicate detection.
std::unordered_set<uint64_t> banIndex;
uint64_t key = banKey(ipAddr, cidr);
if (banIndex.count(key)) {
banList_t::iterator oldit = std::find(banList.begin(), banList.end(), toban);
if (oldit != banList.end()) *oldit = toban;
} else {
banIndex.insert(key);
banList.push_back(toban);
}
Patch
Fix available: defects/bzflag-0002/patch/bzflag-0002.patch
Two-file patch across AccessControlList.h and AccessControlList.cxx. Adds banIndex, hostBanIndex, and idBanIndex as std::unordered_set shadow indexes. Maintains them on insert; uses them for fast duplicate detection.
What We Ask
A patch is ready for review.
- Confirm receipt and assign a GitHub issue reference (BZFlag-Dev/bzflag).
- Assess severity — fires on every ban list load/merge, quadratic in ban count.
- Coordinate a disclosure date — we target 90 days from first contact.
- We will credit the BZFlag team in the public disclosure. Preferred acknowledgment format welcome.
Contact: see cover email. This brief is confidential until coordinated disclosure.