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
76
defects/nomad/unit/NomadTest.java
Normal file
76
defects/nomad/unit/NomadTest.java
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
import java.util.*;
|
||||
|
||||
/**
|
||||
* CWE-407 unit tests for Nomad new defects.
|
||||
*
|
||||
* nomad-0005: scheduler/reconciler/reconcile_cluster.go ~line 1337
|
||||
* handleReconnectingAllocs() builds a []string replacements slice by following
|
||||
* the NextAllocation linked list, then iterates all allocs with:
|
||||
* slices.Contains(replacements, replacementAlloc.ID)
|
||||
* This is O(|all| × |replacements|) = O(A × R).
|
||||
* In a deployment with many reconnecting allocations and a large alloc set,
|
||||
* this becomes effectively O(A²).
|
||||
* Fix: map[string]struct{} built from the linked-list walk → O(1) membership.
|
||||
*
|
||||
* Note: nomad-0001 through nomad-0004 (bitmap port alloc, stream namespace
|
||||
* filter, vault secrets dedup, checkstore difference) were found in a prior
|
||||
* scan and carry UNDF-2026-000000476 through UNDF-2026-000000479.
|
||||
* nomad-0005 is the reconnect reconciler defect first identified here.
|
||||
*/
|
||||
public class NomadTest {
|
||||
|
||||
// --- nomad-0005 simulation ---
|
||||
|
||||
static boolean containsReplacements_slice(List<String> replacements, String allocID) {
|
||||
return replacements.contains(allocID); // O(R) — defect
|
||||
}
|
||||
|
||||
static boolean containsReplacements_map(Set<String> replacementsSet, String allocID) {
|
||||
return replacementsSet.contains(allocID); // O(1) — fix
|
||||
}
|
||||
|
||||
static void testNomad0005() throws Exception {
|
||||
int A = 2000; // total allocations in a large deployment
|
||||
int R = 500; // length of replacement chain per reconnecting alloc
|
||||
|
||||
List<String> replacementsSlice = new ArrayList<>(R);
|
||||
Set<String> replacementsSet = new HashSet<>(R);
|
||||
for (int i = 0; i < R; i++) {
|
||||
String id = "alloc-replace-" + i;
|
||||
replacementsSlice.add(id);
|
||||
replacementsSet.add(id);
|
||||
}
|
||||
|
||||
// alloc IDs that the outer loop iterates over all allocations
|
||||
List<String> allAllocIDs = new ArrayList<>(A);
|
||||
for (int i = 0; i < A; i++) allAllocIDs.add("alloc-" + i);
|
||||
|
||||
// worst-case candidate: last entry in replacements (tail of chain)
|
||||
String targetID = "alloc-replace-" + (R - 1);
|
||||
|
||||
long t0 = System.nanoTime();
|
||||
int hitSlice = 0;
|
||||
for (String id : allAllocIDs) {
|
||||
if (containsReplacements_slice(replacementsSlice, targetID)) hitSlice++;
|
||||
}
|
||||
long sliceNs = System.nanoTime() - t0;
|
||||
|
||||
long t1 = System.nanoTime();
|
||||
int hitMap = 0;
|
||||
for (String id : allAllocIDs) {
|
||||
if (containsReplacements_map(replacementsSet, targetID)) hitMap++;
|
||||
}
|
||||
long mapNs = System.nanoTime() - t1;
|
||||
|
||||
if (hitSlice != hitMap) throw new AssertionError("result mismatch: " + hitSlice + " vs " + hitMap);
|
||||
double ratio = (double) sliceNs / Math.max(mapNs, 1);
|
||||
System.out.printf("nomad-0005 PASS A=%d R=%d slice=%dns map=%dns ratio=%.1fx%n",
|
||||
A, R, sliceNs, mapNs, ratio);
|
||||
if (ratio < 5.0) throw new AssertionError("expected speedup >= 5x, got " + ratio);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
testNomad0005();
|
||||
System.out.println("ALL PASS");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue