java-topology/defects/root-cern-0003/patch/root-cern-0003-ttree-seqbranches-find.patch

52 lines
2.3 KiB
Diff

# UNDF: UNDF-2026-000001222
--- a/tree/tree/src/TTree.cxx
+++ b/tree/tree/src/TTree.cxx
@@ -5862,6 +5862,12 @@ void TTree::InitializeBranchLists(bool checkLeafCount)
{
Int_t nbranches = fBranches.GetEntriesFast();
+ // CWE-407: fSeqBranches is std::vector<TBranch*>. The two loops below
+ // each call std::find(fSeqBranches.begin(), fSeqBranches.end(), branch),
+ // which is O(S) where S = size of fSeqBranches. With B branches total
+ // and up to B count-leaves, the first loop is O(B * S) = O(B^2) in the
+ // worst case. The second loop is also O(B * S) = O(B^2).
+ // Fix: mirror fSeqBranches in an unordered_set<TBranch*> for O(1) lookup.
+ std::unordered_set<TBranch*> seqBranchSet(fSeqBranches.begin(), fSeqBranches.end());
+
// The special branch fBranchRef needs to be processed sequentially:
// we add it once only.
if (fBranchRef && fBranchRef != fSeqBranches[0]) {
fSeqBranches.push_back(fBranchRef);
+ seqBranchSet.insert(fBranchRef);
}
// The branches to be processed sequentially are those that are the leaf count of another branch
if (checkLeafCount) {
for (Int_t i = 0; i < nbranches; i++) {
TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
auto leafCount = ((TLeaf*)branch->GetListOfLeaves()->At(0))->GetLeafCount();
if (leafCount) {
auto countBranch = leafCount->GetBranch();
- if (std::find(fSeqBranches.begin(), fSeqBranches.end(), countBranch) == fSeqBranches.end()) {
+ if (seqBranchSet.find(countBranch) == seqBranchSet.end()) {
fSeqBranches.push_back(countBranch);
+ seqBranchSet.insert(countBranch);
}
}
}
}
// Any branch that is not a leaf count can be safely processed in parallel when reading
// We need to reset the vector to make sure we do not re-add several times the same branch.
if (!checkLeafCount) {
fSortedBranches.clear();
}
for (Int_t i = 0; i < nbranches; i++) {
Long64_t bbytes = 0;
TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
- if (std::find(fSeqBranches.begin(), fSeqBranches.end(), branch) == fSeqBranches.end()) {
+ if (seqBranchSet.find(branch) == seqBranchSet.end()) {
bbytes = branch->GetTotBytes("*");
fSortedBranches.emplace_back(bbytes, branch);
}
}