64 lines
2.4 KiB
Diff
64 lines
2.4 KiB
Diff
# UNDF: UNDF-2026-000000156
|
|
diff --git a/llvm/include/llvm/Analysis/AssumptionCache.h b/llvm/include/llvm/Analysis/AssumptionCache.h
|
|
index a1b2c3d..b8e7c2d 100644
|
|
--- a/llvm/include/llvm/Analysis/AssumptionCache.h
|
|
+++ b/llvm/include/llvm/Analysis/AssumptionCache.h
|
|
@@ -14,6 +14,7 @@
|
|
#define LLVM_ANALYSIS_ASSUMPTIONCACHE_H
|
|
|
|
#include "llvm/ADT/DenseMap.h"
|
|
+#include "llvm/ADT/DenseSet.h"
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/ADT/ilist_node.h"
|
|
#include "llvm/IR/PassManager.h"
|
|
diff --git a/llvm/lib/Analysis/AssumptionCache.cpp b/llvm/lib/Analysis/AssumptionCache.cpp
|
|
index d2c3e4f..a8b9c1e 100644
|
|
--- a/llvm/lib/Analysis/AssumptionCache.cpp
|
|
+++ b/llvm/lib/Analysis/AssumptionCache.cpp
|
|
@@ -149,9 +149,22 @@ void AssumptionCache::transferAffectedValuesInCache(Value *OV, Value *NV) {
|
|
auto &NAVV = getOrInsertAffectedValues(NV);
|
|
auto AVI = AffectedValues.find(OV);
|
|
if (AVI == AffectedValues.end())
|
|
return;
|
|
|
|
- for (auto &A : AVI->second)
|
|
- if (!llvm::is_contained(NAVV, A))
|
|
- NAVV.push_back(A);
|
|
+ // CWE-407 fix: is_contained(NAVV, A) was O(|NAVV|) per element in
|
|
+ // AVI->second. If |NAVV|=M and |AVI->second|=N, the old code ran in
|
|
+ // O(N*M). Build a DenseSet from NAVV once for O(1) per lookup.
|
|
+ //
|
|
+ // ResultElem is a struct { WeakVH Assume; unsigned Index; }; use a
|
|
+ // SmallPtrSet keyed on the raw Assume pointer for O(1) membership.
|
|
+ SmallPtrSet<Value *, 16> NAVVSet;
|
|
+ for (auto &E : NAVV)
|
|
+ if (Value *V = E.Assume)
|
|
+ NAVVSet.insert(V);
|
|
+
|
|
+ for (auto &A : AVI->second) {
|
|
+ Value *V = A.Assume;
|
|
+ if (V && NAVVSet.insert(V).second)
|
|
+ NAVV.push_back(A); // O(1) amortized; O(N+M) total
|
|
+ }
|
|
AffectedValues.erase(OV);
|
|
}
|
|
|
|
# Ticket: llvm-0005
|
|
# File: llvm/lib/Analysis/AssumptionCache.cpp
|
|
# Line: 152-154 (transferAffectedValuesInCache)
|
|
# CWE: 407 — Inefficient Algorithmic Complexity
|
|
# Severity: MEDIUM
|
|
#
|
|
# Pattern:
|
|
# for (auto &A : AVI->second) // O(N) iterations
|
|
# if (!llvm::is_contained(NAVV, A)) // O(M) linear scan
|
|
# NAVV.push_back(A);
|
|
#
|
|
# NAVV is a SmallVector<ResultElem, 1>. is_contained() walks it linearly.
|
|
# When a value that many assumptions affect is replaced (e.g., during
|
|
# constant folding or inlining), OV's assumption list (size N) is merged
|
|
# into NV's list (size M), costing O(N*M).
|
|
#
|
|
# Fix: pre-build a SmallPtrSet from NAVV before the loop; O(N+M) total.
|
|
#
|
|
# Speedup: O(N*M) → O(N+M). For typical N=M=K: O(K^2) → O(K).
|