java-topology/defects/javac/patch/javac-0007-inferencecontext-notify-diff-hoist.patch

45 lines
2.5 KiB
Diff
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 10100 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)