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
This commit is contained in:
parent
b3842ab6b8
commit
9934133dcf
260 changed files with 18278 additions and 15 deletions
203
defects/tomcat/unit/TomcatReplicationValveTest.java
Normal file
203
defects/tomcat/unit/TomcatReplicationValveTest.java
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
package unit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Unit test for CWE-407 tomcat-0001:
|
||||
* ReplicationValve.registerReplicationSession() uses ArrayList.contains()
|
||||
* for cross-context session deduplication — O(n²) for n registrations.
|
||||
*
|
||||
* Run: java -ea -cp . unit.TomcatReplicationValveTest
|
||||
*/
|
||||
public class TomcatReplicationValveTest {
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Models — stand-ins for DeltaSession (identity equality, no Tomcat deps)
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
static final class Session {
|
||||
final String id;
|
||||
Session(String id) { this.id = id; }
|
||||
@Override public String toString() { return "Session(" + id + ")"; }
|
||||
}
|
||||
|
||||
/** Defective: ArrayList-based cross-context session registry (Tomcat original). */
|
||||
static final class DefectiveRegistry {
|
||||
private final List<Session> sessions = new ArrayList<>();
|
||||
long containsProbes = 0;
|
||||
|
||||
public void register(Session s) {
|
||||
// Simulate ArrayList.contains() probe count
|
||||
containsProbes += sessions.size();
|
||||
if (!sessions.contains(s)) {
|
||||
sessions.add(s);
|
||||
}
|
||||
}
|
||||
|
||||
public List<Session> getSessions() { return sessions; }
|
||||
}
|
||||
|
||||
/** Fixed: LinkedHashSet-based registry — O(1) dedup, no contains() guard. */
|
||||
static final class FixedRegistry {
|
||||
private final LinkedHashSet<Session> sessions = new LinkedHashSet<>();
|
||||
long containsProbes = 0;
|
||||
|
||||
public void register(Session s) {
|
||||
containsProbes += 1; // O(1) hash probe
|
||||
sessions.add(s); // Set.add() is idempotent
|
||||
}
|
||||
|
||||
public LinkedHashSet<Session> getSessions() { return sessions; }
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Test 1 — correctness: same unique sessions survive dedup
|
||||
// -----------------------------------------------------------------------
|
||||
static void test1_correctness() {
|
||||
int N = 20;
|
||||
Session[] allSessions = new Session[N];
|
||||
for (int i = 0; i < N; i++) allSessions[i] = new Session("s" + i);
|
||||
|
||||
DefectiveRegistry def = new DefectiveRegistry();
|
||||
FixedRegistry fix = new FixedRegistry();
|
||||
|
||||
// Register each session twice (duplicate registrations)
|
||||
for (Session s : allSessions) { def.register(s); fix.register(s); }
|
||||
for (Session s : allSessions) { def.register(s); fix.register(s); }
|
||||
|
||||
assert def.getSessions().size() == N
|
||||
: "tomcat-0001 correctness: defective size=" + def.getSessions().size() + " expected=" + N;
|
||||
assert fix.getSessions().size() == N
|
||||
: "tomcat-0001 correctness: fixed size=" + fix.getSessions().size() + " expected=" + N;
|
||||
|
||||
// Same sessions in same order
|
||||
List<Session> defList = def.getSessions();
|
||||
List<Session> fixList = new ArrayList<>(fix.getSessions());
|
||||
assert defList.equals(fixList)
|
||||
: "tomcat-0001 correctness: session lists differ";
|
||||
|
||||
System.out.println("PASS test1_correctness: " + N + " unique sessions after 2x registration each");
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Test 2 — complexity: O(n²) probes vs O(n) probes
|
||||
// -----------------------------------------------------------------------
|
||||
static void test2_complexity_ratio() {
|
||||
// Small: N=50, Large: N=500 — unique sessions each time (no early exit)
|
||||
int small = 50;
|
||||
int large = 500;
|
||||
|
||||
DefectiveRegistry defSmall = new DefectiveRegistry();
|
||||
DefectiveRegistry defLarge = new DefectiveRegistry();
|
||||
FixedRegistry fixSmall = new FixedRegistry();
|
||||
FixedRegistry fixLarge = new FixedRegistry();
|
||||
|
||||
// Register N unique sessions (all new — worst case for defective: no early miss)
|
||||
for (int i = 0; i < small; i++) {
|
||||
Session s = new Session("s" + i);
|
||||
defSmall.register(s);
|
||||
fixSmall.register(s);
|
||||
}
|
||||
for (int i = 0; i < large; i++) {
|
||||
Session s = new Session("s" + i);
|
||||
defLarge.register(s);
|
||||
fixLarge.register(s);
|
||||
}
|
||||
|
||||
double defRatio = (double) defLarge.containsProbes / Math.max(defSmall.containsProbes, 1);
|
||||
double fixRatio = (double) fixLarge.containsProbes / Math.max(fixSmall.containsProbes, 1);
|
||||
|
||||
System.out.printf(" defective probes: small=%d large=%d ratio=%.1fx%n",
|
||||
defSmall.containsProbes, defLarge.containsProbes, defRatio);
|
||||
System.out.printf(" fixed probes: small=%d large=%d ratio=%.1fx%n",
|
||||
fixSmall.containsProbes, fixLarge.containsProbes, fixRatio);
|
||||
|
||||
// 10x input → ~100x probes (quadratic)
|
||||
assert defRatio > 50.0
|
||||
: "tomcat-0001 complexity: defective ratio should be >50x at 10x scale, got " + defRatio;
|
||||
// 10x input → ~10x probes (linear)
|
||||
assert fixRatio < 20.0
|
||||
: "tomcat-0001 complexity: fixed ratio should be <20x at 10x scale, got " + fixRatio;
|
||||
assert defRatio > fixRatio * 3
|
||||
: "tomcat-0001 complexity: defective should grow much faster, def=" + defRatio + " fix=" + fixRatio;
|
||||
|
||||
System.out.printf("PASS test2_complexity_ratio: defective=%.0fx fixed=%.0fx%n", defRatio, fixRatio);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Test 3 — absolute counts at N=200
|
||||
// -----------------------------------------------------------------------
|
||||
static void test3_absolute_counts() {
|
||||
int N = 200;
|
||||
DefectiveRegistry def = new DefectiveRegistry();
|
||||
FixedRegistry fix = new FixedRegistry();
|
||||
|
||||
for (int i = 0; i < N; i++) {
|
||||
Session s = new Session("s" + i);
|
||||
def.register(s);
|
||||
fix.register(s);
|
||||
}
|
||||
|
||||
// Defective: probes = 0+1+2+...+(N-1) = N*(N-1)/2
|
||||
long expectedDefMin = (long) N * (N - 1) / 2;
|
||||
assert def.containsProbes >= expectedDefMin
|
||||
: "tomcat-0001 counts: defective probes=" + def.containsProbes + " expected>=" + expectedDefMin;
|
||||
|
||||
// Fixed: exactly N probes (one per registration)
|
||||
assert fix.containsProbes == N
|
||||
: "tomcat-0001 counts: fixed probes=" + fix.containsProbes + " expected=" + N;
|
||||
|
||||
long speedup = def.containsProbes / fix.containsProbes;
|
||||
System.out.printf("PASS test3_absolute_counts: defective=%d fixed=%d speedup=%dx%n",
|
||||
def.containsProbes, fix.containsProbes, speedup);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Test 4 — duplicate registration preserves single entry
|
||||
// -----------------------------------------------------------------------
|
||||
static void test4_duplicate_single_entry() {
|
||||
Session s = new Session("shared");
|
||||
FixedRegistry fix = new FixedRegistry();
|
||||
|
||||
for (int i = 0; i < 50; i++) fix.register(s);
|
||||
|
||||
assert fix.getSessions().size() == 1
|
||||
: "tomcat-0001 dedup: expected 1 entry after 50 identical registrations, got " + fix.getSessions().size();
|
||||
assert fix.getSessions().contains(s)
|
||||
: "tomcat-0001 dedup: session not found after registration";
|
||||
|
||||
System.out.println("PASS test4_duplicate_single_entry: 50 registrations → 1 entry");
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// main
|
||||
// -----------------------------------------------------------------------
|
||||
public static void main(String[] args) {
|
||||
System.out.println("=== TomcatReplicationValveTest — CWE-407 tomcat-0001 ===");
|
||||
int passed = 0;
|
||||
int failed = 0;
|
||||
|
||||
Runnable[] tests = {
|
||||
TomcatReplicationValveTest::test1_correctness,
|
||||
TomcatReplicationValveTest::test2_complexity_ratio,
|
||||
TomcatReplicationValveTest::test3_absolute_counts,
|
||||
TomcatReplicationValveTest::test4_duplicate_single_entry,
|
||||
};
|
||||
|
||||
for (Runnable test : tests) {
|
||||
try {
|
||||
test.run();
|
||||
passed++;
|
||||
} catch (AssertionError e) {
|
||||
System.out.println("FAIL: " + e.getMessage());
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("---");
|
||||
System.out.println("Results: " + passed + " passed, " + failed + " failed");
|
||||
if (failed > 0) System.exit(1);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue