undf: assign 768-770; stamp minio patches

This commit is contained in:
russell@unturf.com 2026-03-30 10:25:20 -04:00
parent cb853893e5
commit 79a77db4f8
28 changed files with 176 additions and 18 deletions

View file

@ -0,0 +1,39 @@
# UNDF: UNDF-2026-000000152
# UNDF: (leave blank)
# CWE-407: DAGCombiner::visitTokenFactor uses is_contained(TFs, ...) O(N²)
#
# In visitTokenFactor, the TFs worklist (SmallVector<SDNode*, 8>) deduplicates
# entries using llvm::is_contained(), which is O(N) per check. The outer loop
# iterates over TFs as it grows, yielding O(T²) where T is the number of
# inlined token factors (bounded by TokenFactorInlineLimit, default 2048).
#
# Meanwhile, the Ops dedup already uses SmallPtrSet<SDNode*, 16> (SeenOps).
# The fix is to add a SmallPtrSet for TFs membership checking, mirroring the
# existing SeenOps pattern.
#
# Severity: MEDIUM — up to 2048² = 4M linear scans during DAG combining,
# which runs on every function compiled. In practice bounded by
# TokenFactorInlineLimit but quadratic within that bound.
#
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -2246,6 +2246,7 @@
SmallVector<SDNode *, 8> TFs; // List of token factors to visit.
SmallVector<SDValue, 8> Ops; // Ops for replacing token factor.
SmallPtrSet<SDNode*, 16> SeenOps;
+ SmallPtrSet<SDNode*, 16> SeenTFs; // O(1) dedup for TFs worklist
bool Changed = false; // If we should replace this token factor.
// Start out with this token factor.
TFs.push_back(N);
+ SeenTFs.insert(N);
// Iterate through token factors. The TFs grows when new token factors are
// encountered.
@@ -2280,7 +2282,7 @@
case ISD::TokenFactor:
- if (Op.hasOneUse() && !is_contained(TFs, Op.getNode())) {
+ if (Op.hasOneUse() && SeenTFs.insert(Op.getNode()).second) {
// Queue up for processing.
TFs.push_back(Op.getNode());
Changed = true;

View file

@ -0,0 +1,46 @@
# UNDF: (leave blank)
# CWE-407: HotColdSplitting getOutliningPenalty Region membership O(R²)
#
# In getOutliningPenalty, Region is an ArrayRef<BasicBlock*>. Two nested
# loops call is_contained(Region, ...) for successor/predecessor membership:
#
# 1) Line 322: for BB in Region → for SuccBB in successors(BB) →
# is_contained(Region, SuccBB) → O(R² × S)
#
# 2) Line 340: for ExitBB → for PHI → for incoming →
# is_contained(Region, getIncomingBlock) → O(E × P × V × R)
#
# Fix: build a SmallPtrSet<BasicBlock*> from Region once at function entry,
# then use O(1) set lookups instead of O(R) linear scans.
#
# Severity: MEDIUM — cold regions in large functions can have hundreds of
# blocks; HotColdSplitting runs as part of the default optimization pipeline.
#
--- a/llvm/lib/Transforms/IPO/HotColdSplitting.cpp
+++ b/llvm/lib/Transforms/IPO/HotColdSplitting.cpp
@@ -299,6 +299,9 @@
static int getOutliningPenalty(ArrayRef<BasicBlock *> Region,
unsigned NumInputs, unsigned NumOutputs) {
int Penalty = SplittingThreshold;
+ // Build a set for O(1) region membership tests (was O(R) linear scan).
+ SmallPtrSet<BasicBlock *, 16> RegionSet(Region.begin(), Region.end());
+
LLVM_DEBUG(dbgs() << "Applying penalty for splitting: " << Penalty << "\n");
// If the splitting threshold is set at or below zero, skip the usual
@@ -321,7 +324,7 @@
for (BasicBlock *SuccBB : successors(BB)) {
- if (!is_contained(Region, SuccBB)) {
+ if (!RegionSet.count(SuccBB)) {
NoBlocksReturn = false;
SuccsOutsideRegion.insert(SuccBB);
}
@@ -340,7 +343,7 @@
int NumIncomingVals = 0;
for (unsigned i = 0; i < PN.getNumIncomingValues(); ++i)
- if (llvm::is_contained(Region, PN.getIncomingBlock(i))) {
+ if (RegionSet.count(PN.getIncomingBlock(i))) {
++NumIncomingVals;
if (NumIncomingVals > 1) {
++NumSplitExitPhis;