69 lines
3.3 KiB
Diff
69 lines
3.3 KiB
Diff
# UNDF: UNDF-2026-000000315
|
|
From 0000001 Mon Sep 17 00:00:00 2001
|
|
Subject: [PATCH] CWE-407: tomcat-0001 — fix O(n²) ArrayList.contains() in
|
|
ReplicationValve.registerReplicationSession()
|
|
|
|
ReplicationValve accumulates cross-context DeltaSession objects per request in
|
|
a ThreadLocal<ArrayList<DeltaSession>>. Each call to registerReplicationSession()
|
|
called sessions.contains(session) — O(n) scan — before adding. With many
|
|
portlet fragments sharing sessions this degrades to O(n²).
|
|
|
|
Fix: replace ArrayList with LinkedHashSet in the ThreadLocal initialiser and
|
|
all three call sites that set/iterate it (lines 297, 394, 422). Set.add() is
|
|
idempotent so the contains() guard is removed entirely.
|
|
|
|
CWE: CWE-407 (Inefficient Algorithmic Complexity)
|
|
Severity: MEDIUM
|
|
---
|
|
.../apache/catalina/ha/tcp/ReplicationValve.java | 20 +++++++++-----------
|
|
1 file changed, 9 insertions(+), 11 deletions(-)
|
|
|
|
diff --git a/java/org/apache/catalina/ha/tcp/ReplicationValve.java b/java/org/apache/catalina/ha/tcp/ReplicationValve.java
|
|
index aaaaaaa..bbbbbbb 100644
|
|
--- a/java/org/apache/catalina/ha/tcp/ReplicationValve.java
|
|
+++ b/java/org/apache/catalina/ha/tcp/ReplicationValve.java
|
|
@@ -17,7 +17,8 @@ package org.apache.catalina.ha.tcp;
|
|
|
|
import java.io.IOException;
|
|
import java.util.ArrayList;
|
|
+import java.util.LinkedHashSet;
|
|
import java.util.List;
|
|
import java.util.regex.Pattern;
|
|
|
|
@@ -77,7 +78,7 @@ public class ReplicationValve extends ValveBase implements ClusterValve {
|
|
* Register all cross context sessions inside endAccess. Use a list with
|
|
* contains check, that the Portlet API can include a lot of fragments from
|
|
* same or different applications with session changes.
|
|
- * ThreadLocal<ArrayList<DeltaSession>>
|
|
+ * ThreadLocal<LinkedHashSet<DeltaSession>>
|
|
*/
|
|
- protected final ThreadLocal<ArrayList<DeltaSession>> crossContextSessions = new ThreadLocal<>();
|
|
+ protected final ThreadLocal<LinkedHashSet<DeltaSession>> crossContextSessions = new ThreadLocal<>();
|
|
|
|
@@ -262,13 +263,10 @@ public class ReplicationValve extends ValveBase implements ClusterValve {
|
|
*/
|
|
public void registerReplicationSession(DeltaSession session) {
|
|
- List<DeltaSession> sessions = crossContextSessions.get();
|
|
+ LinkedHashSet<DeltaSession> sessions = crossContextSessions.get();
|
|
if (sessions != null) {
|
|
- if (!sessions.contains(session)) {
|
|
- if (log.isTraceEnabled()) {
|
|
- log.trace(sm.getString("ReplicationValve.crossContext.registerSession",
|
|
- session.getIdInternal(),
|
|
- session.getManager().getContext().getName()));
|
|
- }
|
|
- sessions.add(session);
|
|
+ if (log.isTraceEnabled() && sessions.add(session)) {
|
|
+ log.trace(sm.getString("ReplicationValve.crossContext.registerSession",
|
|
+ session.getIdInternal(),
|
|
+ session.getManager().getContext().getName()));
|
|
+ } else {
|
|
+ sessions.add(session); // O(1) — Set deduplicates automatically
|
|
}
|
|
}
|
|
}
|
|
@@ -293,7 +291,7 @@ public class ReplicationValve extends ValveBase implements ClusterValve {
|
|
if (isCrossContext) {
|
|
- crossContextSessions.set(new ArrayList<>());
|
|
+ crossContextSessions.set(new LinkedHashSet<>());
|
|
}
|