pygame/libgdx: CWE-407 findings
pygame: CLEAN — runtime uses dict/set throughout (O(1) membership) libgdx-0002: ModelBuilder.rebuildReferences Array.contains O(P*M) — patch libgdx-0005: Stage.touchDragged touchFocuses.contains O(F^2) — patch libgdx-0006: AfterAction.delegate currentActions.indexOf O(W*A) per frame — patch unit: extend LibGDXTest to 7 tests, all PASS (50x-1971x speedup measured)
This commit is contained in:
parent
ec395a01fc
commit
783e406633
11 changed files with 816 additions and 3 deletions
165
defects/nats-server/unit/NatsServerTest.java
Normal file
165
defects/nats-server/unit/NatsServerTest.java
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
import java.util.*;
|
||||
|
||||
/**
|
||||
* CWE-407 unit test — NATS Server nats-server-0001
|
||||
*
|
||||
* server/reload.go diffRoutes()
|
||||
* Two nested O(R) loops compare every old URL against every new URL.
|
||||
* Complexity: O(R²) where R = number of route URLs.
|
||||
* Large NATS clusters can carry hundreds of route URLs; config-reload
|
||||
* (triggered by SIGHUP or file watcher) executes diffRoutes on every reload.
|
||||
*
|
||||
* Fix: build map[string]struct{} keyed on url.String() for each list,
|
||||
* then two single-pass O(R) sweeps replace the double loop → O(R) total.
|
||||
*/
|
||||
public class NatsServerTest {
|
||||
|
||||
// ---- defect simulation --------------------------------------------------
|
||||
|
||||
/** O(R²): for each old URL, scan all new URLs for a match. */
|
||||
static void diffRoutes_quadratic(List<String> old, List<String> newList,
|
||||
List<String> add, List<String> remove) {
|
||||
outer:
|
||||
for (String oldRoute : old) {
|
||||
for (String newRoute : newList) {
|
||||
if (oldRoute.equals(newRoute)) {
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
remove.add(oldRoute);
|
||||
}
|
||||
outer:
|
||||
for (String newRoute : newList) {
|
||||
for (String oldRoute : old) {
|
||||
if (newRoute.equals(oldRoute)) {
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
add.add(newRoute);
|
||||
}
|
||||
}
|
||||
|
||||
// ---- fix simulation -----------------------------------------------------
|
||||
|
||||
/** O(R): build HashSets, then single-pass each list. */
|
||||
static void diffRoutes_linear(List<String> old, List<String> newList,
|
||||
List<String> add, List<String> remove) {
|
||||
Set<String> newSet = new HashSet<>(newList);
|
||||
Set<String> oldSet = new HashSet<>(old);
|
||||
for (String o : old) {
|
||||
if (!newSet.contains(o)) remove.add(o);
|
||||
}
|
||||
for (String n : newList) {
|
||||
if (!oldSet.contains(n)) add.add(n);
|
||||
}
|
||||
}
|
||||
|
||||
// ---- helpers ------------------------------------------------------------
|
||||
|
||||
static List<String> makeRoutes(int base, int count) {
|
||||
List<String> urls = new ArrayList<>(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
urls.add("nats://node-" + (base + i) + ".cluster.local:6222");
|
||||
}
|
||||
return urls;
|
||||
}
|
||||
|
||||
// ---- tests --------------------------------------------------------------
|
||||
|
||||
static void testCorrectnessSmall() {
|
||||
List<String> old = Arrays.asList(
|
||||
"nats://a:6222", "nats://b:6222", "nats://c:6222"
|
||||
);
|
||||
List<String> newList = Arrays.asList(
|
||||
"nats://b:6222", "nats://c:6222", "nats://d:6222"
|
||||
);
|
||||
|
||||
List<String> addQ = new ArrayList<>(), removeQ = new ArrayList<>();
|
||||
List<String> addL = new ArrayList<>(), removeL = new ArrayList<>();
|
||||
diffRoutes_quadratic(old, newList, addQ, removeQ);
|
||||
diffRoutes_linear(old, newList, addL, removeL);
|
||||
|
||||
Collections.sort(addQ); Collections.sort(addL);
|
||||
Collections.sort(removeQ); Collections.sort(removeL);
|
||||
assert addQ.equals(addL) : "add mismatch: " + addQ + " vs " + addL;
|
||||
assert removeQ.equals(removeL) : "remove mismatch: " + removeQ + " vs " + removeL;
|
||||
assert addL.equals(Arrays.asList("nats://d:6222")) : "expected d to be added";
|
||||
assert removeL.equals(Arrays.asList("nats://a:6222")) : "expected a to be removed";
|
||||
System.out.println("PASS testCorrectnessSmall");
|
||||
}
|
||||
|
||||
static void testEmptyOld() {
|
||||
List<String> old = Collections.emptyList();
|
||||
List<String> newList = Arrays.asList("nats://x:6222", "nats://y:6222");
|
||||
List<String> addQ = new ArrayList<>(), removeQ = new ArrayList<>();
|
||||
List<String> addL = new ArrayList<>(), removeL = new ArrayList<>();
|
||||
diffRoutes_quadratic(old, newList, addQ, removeQ);
|
||||
diffRoutes_linear(old, newList, addL, removeL);
|
||||
assert addQ.equals(addL) && removeQ.equals(removeL) : "empty-old mismatch";
|
||||
System.out.println("PASS testEmptyOld");
|
||||
}
|
||||
|
||||
static void testEmptyNew() {
|
||||
List<String> old = Arrays.asList("nats://x:6222", "nats://y:6222");
|
||||
List<String> newList = Collections.emptyList();
|
||||
List<String> addQ = new ArrayList<>(), removeQ = new ArrayList<>();
|
||||
List<String> addL = new ArrayList<>(), removeL = new ArrayList<>();
|
||||
diffRoutes_quadratic(old, newList, addQ, removeQ);
|
||||
diffRoutes_linear(old, newList, addL, removeL);
|
||||
assert addQ.equals(addL) && removeQ.equals(removeL) : "empty-new mismatch";
|
||||
System.out.println("PASS testEmptyNew");
|
||||
}
|
||||
|
||||
static void testIdenticalLists() {
|
||||
List<String> old = Arrays.asList("nats://a:6222", "nats://b:6222");
|
||||
List<String> newList = new ArrayList<>(old);
|
||||
List<String> addQ = new ArrayList<>(), removeQ = new ArrayList<>();
|
||||
List<String> addL = new ArrayList<>(), removeL = new ArrayList<>();
|
||||
diffRoutes_quadratic(old, newList, addQ, removeQ);
|
||||
diffRoutes_linear(old, newList, addL, removeL);
|
||||
assert addQ.isEmpty() && removeQ.isEmpty() : "identical: unexpected diff (quadratic)";
|
||||
assert addL.isEmpty() && removeL.isEmpty() : "identical: unexpected diff (linear)";
|
||||
System.out.println("PASS testIdenticalLists");
|
||||
}
|
||||
|
||||
static void testBenchmarkRatio() {
|
||||
// Simulate a large NATS cluster: R=300 route URLs, 1 change on reload
|
||||
int R = 300;
|
||||
List<String> old = makeRoutes(0, R);
|
||||
List<String> newList = makeRoutes(1, R); // shifted by 1 → 1 remove, 1 add
|
||||
|
||||
int ITERS = 200;
|
||||
|
||||
long t0 = System.nanoTime();
|
||||
for (int i = 0; i < ITERS; i++) {
|
||||
List<String> add = new ArrayList<>(), remove = new ArrayList<>();
|
||||
diffRoutes_quadratic(old, newList, add, remove);
|
||||
}
|
||||
long quadraticNs = System.nanoTime() - t0;
|
||||
|
||||
long t1 = System.nanoTime();
|
||||
for (int i = 0; i < ITERS; i++) {
|
||||
List<String> add = new ArrayList<>(), remove = new ArrayList<>();
|
||||
diffRoutes_linear(old, newList, add, remove);
|
||||
}
|
||||
long linearNs = System.nanoTime() - t1;
|
||||
|
||||
double ratio = (double) quadraticNs / linearNs;
|
||||
System.out.printf("BENCH R=%d iters=%d quadratic=%.1fms linear=%.1fms ratio=%.1fx%n",
|
||||
R, ITERS,
|
||||
quadraticNs / 1e6,
|
||||
linearNs / 1e6,
|
||||
ratio);
|
||||
assert ratio >= 2.0 : "Expected >=2x speedup at R=" + R + ", got " + ratio;
|
||||
System.out.println("PASS testBenchmarkRatio");
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
testCorrectnessSmall();
|
||||
testEmptyOld();
|
||||
testEmptyNew();
|
||||
testIdenticalLists();
|
||||
testBenchmarkRatio();
|
||||
System.out.println("ALL PASS");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue