whitepaper: re-add 10 missing entries + 11 new defects this session, count 578→590; rebuild PDF
This commit is contained in:
parent
e4ee168b1e
commit
2e4f7807d5
401 changed files with 3914 additions and 114 deletions
|
|
@ -1,3 +1,4 @@
|
|||
# UNDF: UNDF-2026-000000117
|
||||
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/GraphUtils.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/GraphUtils.java
|
||||
index 8620caf3..8c99c9ed 100644
|
||||
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/GraphUtils.java
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# UNDF: UNDF-2026-000000118
|
||||
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java
|
||||
index f5e9bfcd..f4bb9a54 100644
|
||||
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# UNDF: UNDF-2026-000000119
|
||||
diff --git a/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java b/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java
|
||||
index cebca6fb..5514eb20 100644
|
||||
--- a/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# UNDF: UNDF-2026-000000120
|
||||
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Dependencies.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Dependencies.java
|
||||
index 48f29c2a..841b18d1 100644
|
||||
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Dependencies.java
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# UNDF: UNDF-2026-000000121
|
||||
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/InferenceContext.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/InferenceContext.java
|
||||
index 8fc316c8..66a8e35a 100644
|
||||
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/InferenceContext.java
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
# UNDF: UNDF-2026-000000122
|
||||
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
|
||||
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
|
||||
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
|
||||
@@ -3231,11 +3231,13 @@ public List<MethodSymbol> interfaceCandidates(Type site, MethodSymbol ms) {
|
||||
CandidatesCache.Entry e = candidatesCache.new Entry(site, ms);
|
||||
List<MethodSymbol> candidates = candidatesCache.get(e);
|
||||
if (candidates == null) {
|
||||
Predicate<Symbol> filter = new MethodFilter(ms, site);
|
||||
- List<MethodSymbol> candidates2 = List.nil();
|
||||
+ LinkedHashSet<MethodSymbol> seen = new LinkedHashSet<>();
|
||||
+ List<MethodSymbol> candidates2 = List.nil();
|
||||
for (Symbol s : membersClosure(site, false).getSymbols(filter)) {
|
||||
if (!site.tsym.isInterface() && !s.owner.isInterface()) {
|
||||
return List.of((MethodSymbol)s);
|
||||
- } else if (!candidates2.contains(s)) {
|
||||
- candidates2 = candidates2.prepend((MethodSymbol)s);
|
||||
+ } else if (seen.add((MethodSymbol)s)) {
|
||||
+ candidates2 = candidates2.prepend((MethodSymbol)s);
|
||||
}
|
||||
}
|
||||
candidates = prune(candidates2);
|
||||
|
||||
# Also requires import:
|
||||
# import java.util.LinkedHashSet; (already present in Types.java via java.util.*)
|
||||
|
||||
# CWE-407: O(S²) → O(S)
|
||||
# Types.java line 3240 — interfaceCandidates
|
||||
#
|
||||
# DEFECTIVE:
|
||||
# List<MethodSymbol> candidates2 = List.nil();
|
||||
# for (Symbol s : membersClosure(...).getSymbols(filter)) {
|
||||
# ...
|
||||
# } else if (!candidates2.contains(s)) { // O(S) linear scan on javac List
|
||||
# candidates2 = candidates2.prepend(...);
|
||||
# }
|
||||
#
|
||||
# candidates2 is a singly-linked javac List<MethodSymbol>.
|
||||
# List.contains() is O(S) — it walks every node.
|
||||
# As symbols accumulate, the S-th symbol triggers a scan of S-1 elements.
|
||||
# Total work: 1+2+...+S = O(S²).
|
||||
#
|
||||
# TRIGGER: deep diamond interface hierarchies — e.g., a class implementing
|
||||
# two interfaces both extending a common generic interface with many method
|
||||
# overloads. Each unique (site, method) pair is computed once (then cached),
|
||||
# but with N classes × M methods the first-pass cost is O(N × M × S²).
|
||||
#
|
||||
# FIX: maintain a parallel LinkedHashSet<MethodSymbol> for O(1) duplicate
|
||||
# detection. candidates2 is still built as a List (prepend) to preserve the
|
||||
# existing ordering contract; seen handles the dedup guard.
|
||||
#
|
||||
# Complexity:
|
||||
# Defective: O(S²) per (site, method) pair
|
||||
# Fixed: O(S) per (site, method) pair
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
# UNDF: UNDF-2026-000000123
|
||||
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/InferenceContext.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/InferenceContext.java
|
||||
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/InferenceContext.java
|
||||
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/InferenceContext.java
|
||||
@@ -290,9 +290,10 @@ void notifyChange(List<Type> inferredVars) {
|
||||
InferenceException thrownEx = null;
|
||||
+ List<Type> remainingVars = inferencevars.diff(inferredVars);
|
||||
for (Map.Entry<FreeTypeListener, List<Type>> entry :
|
||||
new LinkedHashMap<>(freeTypeListeners).entrySet()) {
|
||||
- if (!Type.containsAny(entry.getValue(), inferencevars.diff(inferredVars))) {
|
||||
+ if (!Type.containsAny(entry.getValue(), remainingVars)) {
|
||||
try {
|
||||
entry.getKey().typesInferred(this);
|
||||
freeTypeListeners.remove(entry.getKey());
|
||||
|
||||
# CWE-407: O(L × N × M) → O(N×M + L×V) where V = entry.getValue() size
|
||||
# InferenceContext.java line 294 — notifyChange
|
||||
#
|
||||
# DEFECTIVE:
|
||||
# void notifyChange(List<Type> inferredVars) {
|
||||
# for (Map.Entry<FreeTypeListener, List<Type>> entry : ...) {
|
||||
# if (!Type.containsAny(entry.getValue(),
|
||||
# inferencevars.diff(inferredVars))) { // ← O(N*M) per listener
|
||||
#
|
||||
# inferencevars.diff(inferredVars) calls List.diff() which iterates every element
|
||||
# of inferredVars (M items) and for each does a linear scan of the current list
|
||||
# (up to N items) — cost O(N × M). This is recomputed from scratch on EVERY
|
||||
# iteration of the freeTypeListeners loop (L iterations).
|
||||
# Total: O(L × N × M).
|
||||
#
|
||||
# N = inferencevars count (type variables in scope — can be 10–100 in complex
|
||||
# generic method calls with nested lambdas / multi-level bounded wildcards).
|
||||
# M = inferredVars count (newly resolved variables — often ≈ N in final round).
|
||||
# L = freeTypeListeners count (listeners registered per inference variable —
|
||||
# can be O(N) during complex overload resolution in generic API chains).
|
||||
#
|
||||
# This hits hard on codebases like Spring / Guava / RxJava where deeply nested
|
||||
# generic method calls stack up many inference contexts.
|
||||
#
|
||||
# FIX: hoist diff() out of the loop. The result does not change between
|
||||
# iterations (neither inferencevars nor inferredVars mutate during the loop).
|
||||
#
|
||||
# Complexity:
|
||||
# Defective: O(L × N × M) per notifyChange call
|
||||
# Fixed: O(N×M + L×V) per notifyChange call (V = avg entry.getValue() size)
|
||||
Loading…
Add table
Add a link
Reference in a new issue