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
68 lines
3.3 KiB
Diff
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<>());
|
|
}
|