root-cern-0001: TTreeCache::FillBuffer potentialVetoes std::vector O(N²) per basket/branch — replace with std::unordered_set, 9.8x speedup (MOAD-0001 CWE-407, tree/tree/src/TTreeCache.cxx) root-cern-0002: TWebFile::GetFromWeb10 logs full HTTP request including Authorization: Basic base64(user:password) at gDebug > 0 (HIGH) Also affects TS3WebFile — exposes AWS access key + signature (MOAD-0004 CWE-312, net/net/src/TWebFile.cxx) hexchat: all 5 MOADs CLEAN — binary tree user lookup, single-threaded event loop, raw log is ephemeral in-memory widget only
2.5 KiB
root-cern-0001 — TTreeCache::FillBuffer potentialVetoes O(N²) MOAD-0001
Target
ROOT (CERN data analysis framework) — https://github.com/root-project/root
File
tree/tree/src/TTreeCache.cxx
Pattern
CWE-407: Algorithmic complexity — quadratic basket scan in TTreeCache prefetch planning.
Location
TTreeCache::FillBuffer → inner lambda CollectBaskets, lines ~1381–1511.
Structure:
for (Int_t i = 0; i < fNbranches; ++i) { // outer: branches
potentialVetoes.clear();
b->fCacheInfo.GetUnused(potentialVetoes); // fills vector with unused basket indices
...
for (Int_t j = ...; j < nb; ++j) { // inner: baskets per branch
if (std::find(begin(potentialVetoes), end(potentialVetoes), j) ...)
potentialVetoes is std::vector<Int_t>. std::find on it is O(V) where V = number
of unused baskets. With B branches each having N baskets, total cost is O(B × N²) in
our worst case where all baskets are unused.
Impact
TTreeCache::FillBuffer is called at the start of each cluster read, which happens every few thousand entries during a TTree scan. For physics analysis with many branches and many baskets (common in CMS/ATLAS use), this becomes a significant overhead.
Example: 100 branches × 1000 baskets each → std::find scans up to 1000 elements per basket × 1000 baskets = 1,000,000 comparisons per branch per cluster reload. With 100 branches: 100,000,000 comparisons per cluster. Hash set makes this 100,000.
Severity
MEDIUM — basket count V is bounded per branch but can reach thousands in large physics files. Affects every TTree cache-prefetch cycle.
Fix
Replace std::vector<Int_t> potentialVetoes with std::unordered_set<Int_t>.
- Membership check: O(1) average vs O(V)
- Insert: O(1) average (from GetUnused() output)
- Clear: O(size) same
- The debug iteration loop
for(auto v : potentialVetoes)still works
Speedup
O(B × N²) → O(B × N). At N=1000 baskets per branch: 1000x fewer comparisons in the inner scan.
MOADs checked
- MOAD-0001 (CWE-407): CONFIRMED — see above
- MOAD-0002 (Intertangle): gROOT god-object is intentional ROOT architecture, not a defect we can fix
- MOAD-0003 (Leaked Context): TDirectory uses
thread_localfor gDirectory correctly — CLEAN - MOAD-0004 (CWE-312): TWebFile::GetFromWeb10 logs full HTTP request including Authorization: Basic at gDebug > 0 — see root-cern-0002
- MOAD-0005 (Thundering Herd): TClass::BuildRealData has gInterpreterMutex + double-check inside — acceptable pattern
Date
2026-03-31