package unit; import java.util.*; /** * CWE-407 unit test: cmake-0003 * AddRuntimeDLL — O(n²) std::find before emplace_back vs O(n) set insertion. * * Simulates CMake's AddRuntimeDLL(): * slow: scan vector for membership before push → O(n) per call, O(n²) total * fast: use HashSet for membership check → O(1) per call, O(n) total */ public class RuntimeDllAlgorithm { // Slow: mirrors std::find(begin, end, tgt) == end before emplace_back static long slowAddRuntimeDlls(List dllIds) { long ops = 0; List runtimeDlls = new ArrayList<>(); for (int id : dllIds) { boolean found = false; for (int existing : runtimeDlls) { // O(n) scan ops++; if (existing == id) { found = true; break; } } if (!found) runtimeDlls.add(id); } return ops; } // Fast: unordered_set insertion returns bool (inserted = new) static long fastAddRuntimeDlls(List dllIds) { long ops = 0; Set runtimeDllsSet = new HashSet<>(); List runtimeDlls = new ArrayList<>(); for (int id : dllIds) { ops++; if (runtimeDllsSet.add(id)) { runtimeDlls.add(id); } } return ops; } public static void main(String[] args) { int[] sizes = {100, 500, 1000}; int passed = 0, total = 0; for (int N : sizes) { // D unique DLLs, each referenced twice (common: transitive deps) List dllIds = new ArrayList<>(N * 2); for (int i = 0; i < N; i++) dllIds.add(i); for (int i = 0; i < N; i++) dllIds.add(i); // duplicates long slowOps = slowAddRuntimeDlls(dllIds); long fastOps = fastAddRuntimeDlls(dllIds); double ratio = (double) slowOps / fastOps; total++; System.out.printf("D=%4d slow=%8d fast=%6d ratio=%.1fx%n", N, slowOps, fastOps, ratio); // At D=1000: slow accumulates O(N²/2)=500k ops, fast=2N=2000 assert ratio > 10.0 : "Expected ratio > 10, got " + ratio; passed++; } // Correctness: same unique set produced List input = Arrays.asList(1, 2, 1, 3, 2, 4); List slowResult = new ArrayList<>(); Set seen = new HashSet<>(); for (int id : input) { boolean found = false; for (int x : slowResult) if (x == id) { found = true; break; } if (!found) slowResult.add(id); } Set fastResult = new HashSet<>(); for (int id : input) fastResult.add(id); assert new HashSet<>(slowResult).equals(fastResult) : "Correctness check failed: " + slowResult + " vs " + fastResult; passed++; total++; System.out.printf("%d/%d PASS%n", passed, total); } }