52 lines
2.3 KiB
Diff
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);
|
|
}
|
|
}
|