java-topology/defects/root-cern-0003/SCAN-NOTES.md
russell@unturf.com 09012e7ec1 openfoam+root-cern: 5-MOAD scan; openfoam-0003 CWE-407 DSMCCloud typeIdList O(C*T*M*K), root-cern-0003 CWE-407 TTree::InitializeBranchLists fSeqBranches O(B^2)
openfoam-0003: DSMCCloud::initialise calls findIndex(typeIdList_, moleculeName)
inside triple-nested forAll(cells) * forAll(tets) * forAll(molecules) loop.
Fix: pre-build HashTable<label, word> before cell loop for O(1) lookups.
3-10x speedup depending on type count. 5/5 PASS.

root-cern-0003: TTree::InitializeBranchLists calls std::find on fSeqBranches
(std::vector<TBranch*>) inside two O(B) loops, yielding O(B^2) total.
Fix: mirror fSeqBranches in std::unordered_set<TBranch*> for O(1) lookup.
~500x speedup at B=500, ~1000x at B=1000 (CMS NanoAOD scale). 6/6 PASS.

MOAD-0002: OpenFOAM objectRegistry god-object structural, ROOT gROOT intertangle
structural (gROOTMutex inconsistently applied). Both documented.
MOAD-0003: ROOT TTHREAD_TLS method-scoped only, CLEAN. OpenFOAM no thread-local, CLEAN.
MOAD-0004: OpenFOAM CLEAN. ROOT TWebFile auth logging pre-existing root-cern-0002.
MOAD-0005: Both CLEAN.
2026-04-03 15:31:30 -04:00

2.9 KiB

ROOT (CERN): 5-MOAD scan results (2026-04-03)

MOAD-0001 (CWE-407) -- NEW: root-cern-0003

TTree::InitializeBranchLists() calls std::find on fSeqBranches (std::vector<TBranch*>) twice per branch in two separate loops:

  1. Count-leaf loop: for each of B branches, O(S) scan to check if its count branch is already in fSeqBranches.
  2. Partition loop: for each of B branches, O(S) scan to check if it is a seq branch.

Total: O(B * S) for each loop = O(B^2) in worst case (all count leaves). At B=1000 (CMS NanoAOD scale): ~2,000,000 pointer comparisons vs ~2,000 with std::unordered_set<TBranch*>. Speedup: ~1000x.

Triggered on first GetEntry() with ROOT Implicit MultiThreading (IMT) enabled.

File: tree/tree/src/TTree.cxx, function TTree::InitializeBranchLists.

Pre-existing defects:

  • root-cern-0001: TTreeCache::FillBuffer potentialVetoes std::find O(B*N^2) MEDIUM
  • root-cern-0002: TWebFile GetFromWeb10 Authorization header logged at gDebug>0 HIGH

Other candidates examined:

  • RDFInterfaceUtils.cxx line 202: std::find in for loop but usedCols is bounded by the formula column count (typically <20), not a scaling defect.
  • RGeomData.cxx: std::find on pchlds/chlds, per-node operation only, O(children) bounded.
  • TTree.cxx line 5879/5894: same defect as root-cern-0003, same function.

MOAD-0002 (Intertangle) -- STRUCTURAL, document only

ROOT's gROOT (TROOT) is a global god-object: all TTrees, TChains, TFiles, TDirectories, TH1s register themselves into gROOT->GetListOfSpecials(), GetListOfCleanups(), GetListOfDataSets() etc. The mutex coverage is inconsistent: GetListOfCleanups is guarded by gROOTMutex but GetListOfSpecials and GetListOfDataSets are accessed unguarded (TChain constructor lines 82/89). This is a long-standing architectural coupling that is not addressable with a local patch. ROOT 7 (RNTuple/RDataFrame) moves away from gROOT but TTrees remain.

MOAD-0003 (Leaked Context) -- CLEAN

ROOT's TTHREAD_TLS usage is limited to TMVA internals (MethodMLP, BinaryTree, TNeuron, etc.) holding method-scoped state (iteration counters, random state) rather than request-scoped identity. No web-service or per-request identity propagation via thread-locals found.

MOAD-0004 (CWE-312) -- EXISTING root-cern-0002

TWebFile::GetFromWeb10 at gDebug>0 logs full HTTP request including Authorization: Basic base64(user:password). TS3WebFile similarly logs AWS access keys. Documented in root-cern-0002.

MOAD-0005 (Thundering Herd) -- CLEAN

TFormula::gClingFunctions static unordered_map is consistently guarded by R__LOCKGUARD(gROOTMutex) before every read/write. TGeoParallelWorld static candidates vector is guarded by a dedicated std::mutex in InitSafetyVoxel. RWebDisplayHandle::FindCreator static map lacks a mutex but is called only from GUI display code which ROOT users treat as single-threaded. No unsynchronized cache-get+null+set pattern found in hot paths.