java-topology/defects/kotlin/patch/kotlin-diamond-recursion-CLEAN.md
russell@unturf.com 1dee074618 kafka-0009: GraphGraceSearchUtil diamond recursion O(2^D) → O(N); count 621→622
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).
2026-03-29 16:59:50 -04:00

1.6 KiB
Raw Blame History

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.