findAndVerifyWindowGrace() recurses over parent GraphNodes without a visited accumulator. Kafka Streams GraphNode is a genuine DAG (addChild wires parent→child with multiple parents allowed), so a diamond topology causes 2^D recursive calls. Fix: thread an IdentityHashMap<GraphNode,Long> memo through recursion; memoize on first visit, return cached result on revisit. 8/8 unit tests PASS; D=10 defect count=3071 vs patched O(N). Diamond-recursion CLEAN markers added for: flink, neo4j, janusgraph, tinkerpop, dgraph, zookeeper, storm, ant, gradle, graal, eclipse-jdt, exposed, intellij, kotlin, scala3, hibernate-0007 (prior session work now committed).
1.6 KiB
Kotlin Compiler — Diamond Recursion CWE-407 Scan: CLEAN
Pattern: Recursive cycle/reachability without visited set (O(2^D) on diamond DAGs)
Scan date: 2026-03-29
Scope: compiler/frontend/src/, compiler/
Method
Searched for isCyclic, hasCycle, createsCycle, isReachable, canReach,
hasPath, detectCycle across all Kotlin and Java sources. Examined each
recursive function for missing visited-accumulator parameters.
Key candidates reviewed
findLoopsInSupertypes.kt — isReachable()
compiler/frontend/src/.../resolve/findLoopsInSupertypes.kt line 56.
Called in a loop (line 40) for each supertype. Each call to isReachable() creates
a fresh DFS.VisitedWithSet() and performs a full DFS. This is O(S × (V+E)) where
S = supertype count. Not diamond recursion — each call is independent and properly
visits nodes. CLEAN.
CyclicAnnotationsChecker
compiler/frontend/src/.../resolve/checkers/CyclicAnnotationsChecker.kt.
Checker class maintains instance-level visitedAnnotationDescriptors mutableSetOf.
typeHasCycle() checks visitedAnnotationDescriptors.add() before recursing. CLEAN.
NonExpansiveInheritanceRestrictionChecker.kt
Already addressed by kotlin-0001-collectreachable-hashset.patch — the collectReachable
function returns a HashSet for O(1) membership. Not the diamond recursion pattern.
Verdict
CLEAN for diamond recursion pattern. Kotlin compiler uses DFS.VisitedWithSet()
for all DFS traversal, mutable visited sets for annotation cycle detection,
and existing patches address the unrelated O(N²) List-contains issues.
No unprotected recursive DAG traversal found.