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.2 KiB
1.2 KiB
Diamond Recursion Scan — CLEAN
Scan date: 2026-03-29 Pattern: Recursive cycle/dependency check without visited set (CWE-407 diamond recursion, O(2^D))
Files examined
subprojects/core/src/main/java/org/gradle/execution/plan/DetermineExecutionPlanAction.java— cycle detection,findCyclessubprojects/core/src/main/java/org/gradle/execution/plan/Node.java— dependency nodeplatforms/core-configuration/model-core/src/main/java/org/gradle/model/internal/registry/DefaultModelRegistry.java— model dependency resolution
Findings
DetermineExecutionPlanAction: Uses two HashSet<Node> accumulators (visiting and visited) for DFS traversal. The findCycles method delegates to graphWalker.findCycles() which uses proper SCC cycle detection. CLEAN.
DefaultModelRegistry: Uses a goal state machine (NotSeen / VisitingDependencies / Achieved) where each goal can only be in one state at a time. Goals transition from NotSeen → VisitingDependencies → Achieved, preventing re-traversal. CLEAN.
Note: gradle-0002 covers a pre-existing CWE-407 defect in NodeState.addIncomingEdge ArrayList membership scan.