java-topology/defects/tomcat/patch/tomcat-0001.patch
russell@unturf.com 9934133dcf whitepaper: 312 sites / 151 ecosystems — wave2+3 defect tables and PDF rebuild
Add 88 new defect entries to HIGH and MEDIUM tables:
  HIGH: mysql-0001/0002, mariadb-0001, redis-0001/0002, valkey-0001/0002, openvpn-0001,
        vlc-0001, prometheus-0001, otel-collector-0001, cockroachdb-0001..0004,
        tidb-0001..0008, kubernetes-0001/0002, go-0001, kotlin-0002, scala-0001,
        allegro5-0001, sdl2-0001, grafana-0001, clickhouse-0001, duckdb-0001,
        mongodb-0001, envoy-0001, istio-0001, cilium-0001, linkerd2-0001,
        linux-0001/0002/0003, tor-0002/0003, curl-0001, julia-0001, lua-0001,
        perl5-0001, nats-0001, spring-0003/0004, tomcat-0001, onos-0002, odl-0002

  MEDIUM: helm-0001, mariadb-0002, openssl-0001/0002, memcached-0001,
          cassandra-0001..0004, flink-0001, storm-0001/0002, zookeeper-0001..0003,
          pip-0001, gradle-0001, nginx-0001, haproxy-0001, caddy-0001, varnish-0001,
          ffmpeg-0001, gstreamer-0001, raylib-0001, love2d-0001, php-0001/0002,
          r-source-0001, cpython-0002, ruby-0001, rabbitmq-0003/0004, activemq-0001,
          ovs-0001, onos-0003, odl-0002, jetty-0001

PDF: 976K
2026-03-27 15:23:43 -04:00

68 lines
3.3 KiB
Diff

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<>());
}