java-topology/defects/javac/patch/javac-0003-modulehasher-stackset.patch

36 lines
1.8 KiB
Diff

# 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
+++ b/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java
@@ -264,21 +264,26 @@ public void reverse(Consumer<T> action) {
private void sort() {
Set<T> visited = new HashSet<>();
Deque<T> stack = new ArrayDeque<>();
- graph.nodes.forEach(node -> visit(node, visited, stack));
+ // CWE-407 fix: parallel Set for O(1) stack membership test.
+ // Deque.contains() is O(n); stackSet.contains() is O(1).
+ Set<T> stackSet = new HashSet<>();
+ graph.nodes.forEach(node -> visit(node, visited, stack, stackSet));
}
private Set<T> children(T node) {
return graph.edges().get(node);
}
- private void visit(T node, Set<T> visited, Deque<T> stack) {
+ private void visit(T node, Set<T> visited, Deque<T> stack, Set<T> stackSet) {
if (visited.add(node)) {
stack.push(node);
- children(node).forEach(child -> visit(child, visited, stack));
+ stackSet.add(node);
+ children(node).forEach(child -> visit(child, visited, stack, stackSet));
stack.pop();
+ stackSet.remove(node);
result.addLast(node);
}
- else if (stack.contains(node)) {
+ else if (stackSet.contains(node)) {
throw new IllegalArgumentException(
"Cycle detected: " + node + " -> " + children(node));
}