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
223 lines
8.3 KiB
Java
223 lines
8.3 KiB
Java
package unit;
|
|
|
|
import java.util.*;
|
|
|
|
/**
|
|
* NatsPeerDedupTest — Java model of CWE-407 defect in NATS JetStream cluster.
|
|
*
|
|
* NATS-0001 (MEDIUM): jetstream_cluster.go — peer dedup loop uses slices.Contains.
|
|
* During a stream move/scale, existing peers are deduplicated against a new peer
|
|
* group using:
|
|
*
|
|
* for _, peer := range rg.Peers {
|
|
* if !slices.Contains(nrg.Peers, peer) {
|
|
* peerSet = append(peerSet, peer)
|
|
* }
|
|
* }
|
|
*
|
|
* slices.Contains is O(|nrg.Peers|). Outer loop is O(|rg.Peers|).
|
|
* Total: O(|rg.Peers| * |nrg.Peers|) — quadratic in replica count.
|
|
*
|
|
* Fix: build a map[string]struct{} from nrg.Peers before the loop (O(|nrg|)),
|
|
* then probe in O(1) per rg peer. Total: O(|rg| + |nrg|).
|
|
*/
|
|
public class NatsPeerDedupTest {
|
|
|
|
// -----------------------------------------------------------------------
|
|
// Algorithm models
|
|
// -----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Defective: for each peer in rgPeers, scan all of nrgPeers.
|
|
* Returns exact comparison count (worst-case: no overlap).
|
|
*/
|
|
static long slow(List<String> rgPeers, List<String> nrgPeers) {
|
|
long comparisons = 0;
|
|
List<String> peerSet = new ArrayList<>();
|
|
for (String peer : rgPeers) {
|
|
// slices.Contains inner loop
|
|
boolean found = false;
|
|
for (String nrgPeer : nrgPeers) {
|
|
comparisons++;
|
|
if (peer.equals(nrgPeer)) { found = true; break; }
|
|
}
|
|
if (!found) {
|
|
peerSet.add(peer);
|
|
}
|
|
}
|
|
// append nrg.Peers to peerSet
|
|
peerSet.addAll(nrgPeers);
|
|
return comparisons;
|
|
}
|
|
|
|
/**
|
|
* Fixed: build set from nrgPeers first, then probe O(1) per rg peer.
|
|
* Returns exact operation count (set build + probes).
|
|
*/
|
|
static long fast(List<String> rgPeers, List<String> nrgPeers) {
|
|
long ops = 0;
|
|
// Build set: nrgPeers.size() insertions
|
|
Map<String, Boolean> nrgSet = new HashMap<>();
|
|
for (String p : nrgPeers) {
|
|
nrgSet.put(p, true);
|
|
ops++;
|
|
}
|
|
List<String> peerSet = new ArrayList<>();
|
|
for (String peer : rgPeers) {
|
|
ops++; // O(1) map probe
|
|
if (!nrgSet.containsKey(peer)) {
|
|
peerSet.add(peer);
|
|
}
|
|
}
|
|
peerSet.addAll(nrgPeers);
|
|
return ops;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
// Helper: build disjoint peer lists
|
|
// -----------------------------------------------------------------------
|
|
|
|
static List<String> makePeers(String prefix, int count, int offset) {
|
|
List<String> peers = new ArrayList<>(count);
|
|
for (int i = 0; i < count; i++) {
|
|
peers.add(prefix + (offset + i));
|
|
}
|
|
return peers;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
// Tests
|
|
// -----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Test 1: worst-case N=100 rg peers, M=100 nrg peers, no overlap.
|
|
* slow() = N*M = 10000 comparisons.
|
|
* fast() = N+M = 200 operations.
|
|
* Assert slow > fast * 10x.
|
|
*/
|
|
static void test_nats0001_comparison_ratio() {
|
|
final int N = 100, M = 100;
|
|
List<String> rgPeers = makePeers("rg-", N, 0);
|
|
List<String> nrgPeers = makePeers("nrg-", M, 0); // disjoint
|
|
|
|
long sOps = slow(rgPeers, nrgPeers);
|
|
long fOps = fast(rgPeers, nrgPeers);
|
|
|
|
double ratio = (double) sOps / fOps;
|
|
System.out.printf(" NATS-0001 ratio slow=%d fast=%d ratio=%.1fx%n",
|
|
sOps, fOps, ratio);
|
|
assert sOps > fOps * 10 :
|
|
"NATS-0001: expected slow > fast*10, got slow=" + sOps + " fast=" + fOps;
|
|
}
|
|
|
|
/**
|
|
* Test 2: scaling — doubling N doubles slow() cost, barely changes fast().
|
|
*/
|
|
static void test_nats0001_scaling_with_peer_count() {
|
|
final int M = 50;
|
|
List<String> nrgPeers = makePeers("nrg-", M, 0);
|
|
|
|
List<String> rgLo = makePeers("rg-", 50, 100);
|
|
List<String> rgHi = makePeers("rg-", 500, 100);
|
|
|
|
long sLo = slow(rgLo, nrgPeers);
|
|
long sHi = slow(rgHi, nrgPeers);
|
|
long fLo = fast(rgLo, nrgPeers);
|
|
long fHi = fast(rgHi, nrgPeers);
|
|
|
|
double sScale = (double) sHi / sLo;
|
|
double fScale = (double) fHi / fLo;
|
|
System.out.printf(" NATS-0001 N scaling slowScale=%.1fx fastScale=%.1fx%n",
|
|
sScale, fScale);
|
|
assert sScale > 5.0 : "NATS-0001: slow should scale with N, got " + sScale;
|
|
assert fHi < sHi : "NATS-0001: fast should be cheaper than slow at N=500";
|
|
}
|
|
|
|
/**
|
|
* Test 3: scaling — doubling M doubles slow() cost, fast() scales only linearly.
|
|
*/
|
|
static void test_nats0001_scaling_with_nrg_peer_count() {
|
|
final int N = 50;
|
|
List<String> rgPeers = makePeers("rg-", N, 0);
|
|
|
|
List<String> nrgLo = makePeers("nrg-", 50, 1000);
|
|
List<String> nrgHi = makePeers("nrg-", 500, 1000);
|
|
|
|
long sLo = slow(rgPeers, nrgLo);
|
|
long sHi = slow(rgPeers, nrgHi);
|
|
long fLo = fast(rgPeers, nrgLo);
|
|
long fHi = fast(rgPeers, nrgHi);
|
|
|
|
double sScale = (double) sHi / sLo;
|
|
System.out.printf(" NATS-0001 M scaling slowScale=%.1fx fast_lo=%d fast_hi=%d%n",
|
|
sScale, fLo, fHi);
|
|
assert sScale > 5.0 : "NATS-0001: slow should scale with M, got " + sScale;
|
|
assert fHi < sHi : "NATS-0001: fast should be cheaper than slow at M=500";
|
|
}
|
|
|
|
/**
|
|
* Test 4: correctness — both paths must produce identical peerSet output.
|
|
*/
|
|
static void test_nats0001_correctness() {
|
|
// partial overlap: rg has peers 0-9, nrg has peers 5-14
|
|
List<String> rgPeers = makePeers("peer-", 10, 0); // peer-0..peer-9
|
|
List<String> nrgPeers = makePeers("peer-", 10, 5); // peer-5..peer-14
|
|
|
|
// Run slow path to get result
|
|
List<String> slowResult = new ArrayList<>();
|
|
for (String peer : rgPeers) {
|
|
if (!nrgPeers.contains(peer)) slowResult.add(peer);
|
|
}
|
|
slowResult.addAll(nrgPeers);
|
|
|
|
// Run fast path to get result
|
|
Map<String, Boolean> nrgSet = new HashMap<>();
|
|
for (String p : nrgPeers) nrgSet.put(p, true);
|
|
List<String> fastResult = new ArrayList<>();
|
|
for (String peer : rgPeers) {
|
|
if (!nrgSet.containsKey(peer)) fastResult.add(peer);
|
|
}
|
|
fastResult.addAll(nrgPeers);
|
|
|
|
Collections.sort(slowResult);
|
|
Collections.sort(fastResult);
|
|
|
|
System.out.printf(" NATS-0001 correctness: peerSet size=%d (slow=%d fast=%d)%n",
|
|
slowResult.size(), slowResult.size(), fastResult.size());
|
|
assert slowResult.equals(fastResult) :
|
|
"NATS-0001 correctness: peer sets differ: " + slowResult + " vs " + fastResult;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
// Main
|
|
// -----------------------------------------------------------------------
|
|
|
|
public static void main(String[] args) {
|
|
System.out.println("NatsPeerDedupTest — CWE-407 model tests (NATS-0001)");
|
|
System.out.println("=====================================================");
|
|
|
|
run("test_nats0001_comparison_ratio", NatsPeerDedupTest::test_nats0001_comparison_ratio);
|
|
run("test_nats0001_scaling_with_peer_count", NatsPeerDedupTest::test_nats0001_scaling_with_peer_count);
|
|
run("test_nats0001_scaling_with_nrg_peer_count", NatsPeerDedupTest::test_nats0001_scaling_with_nrg_peer_count);
|
|
run("test_nats0001_correctness", NatsPeerDedupTest::test_nats0001_correctness);
|
|
|
|
System.out.println("=====================================================");
|
|
System.out.println("4/4 PASS");
|
|
}
|
|
|
|
@FunctionalInterface interface TestFn { void run() throws Exception; }
|
|
|
|
static void run(String name, TestFn fn) {
|
|
System.out.print(" [RUN] " + name + " ... ");
|
|
try {
|
|
fn.run();
|
|
System.out.println("PASS");
|
|
} catch (AssertionError e) {
|
|
System.out.println("FAIL — " + e.getMessage());
|
|
System.exit(1);
|
|
} catch (Exception e) {
|
|
System.out.println("ERR — " + e);
|
|
System.exit(1);
|
|
}
|
|
}
|
|
}
|