39 lines
1.7 KiB
Diff
39 lines
1.7 KiB
Diff
# 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;
|