From f2d7a3127e4e78a7bd2811df93fe9eef918a614d Mon Sep 17 00:00:00 2001 From: "russell@unturf.com" Date: Mon, 30 Mar 2026 17:25:38 -0400 Subject: [PATCH] 5-MOAD scan: pcsx2 2 defects, wine 1 defect + 1 MOAD-0004, thunderbird unavailable PCSX2: - pcsx2-0001: Patch::ReloadEnabledLists 4x std::find on vector O(N^2) MEDIUM 6-12x - pcsx2-0002: GSCapture codec dedup std::find_if O(N^2) LOW 11x - MOAD-0002/0003/0004/0005: CLEAN Wine: - wine-0001: ntdll/loader.c find_module_dependency O(D) linked-list dedup HIGH 7x - MOAD-0004: ChangeServiceConfig logs password via debugstr_w MEDIUM - MOAD-0002/0003/0005: CLEAN Thunderbird: source unavailable (nicholasb2101/gecko-dev repo inaccessible) --- defects/thunderbird-0001/CLEAN.md | 6 ++ .../test/LoaderDependencyDedupTest.java | 99 +++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 defects/thunderbird-0001/CLEAN.md create mode 100644 defects/wine-0001/test/LoaderDependencyDedupTest.java diff --git a/defects/thunderbird-0001/CLEAN.md b/defects/thunderbird-0001/CLEAN.md new file mode 100644 index 000000000..62d4b7312 --- /dev/null +++ b/defects/thunderbird-0001/CLEAN.md @@ -0,0 +1,6 @@ +# Thunderbird: Source Unavailable + +Repository `https://github.com/nicholasb2101/gecko-dev` is not accessible +(authentication required or repo does not exist). Both clone attempts failed. + +All 5 MOADs: SKIPPED. diff --git a/defects/wine-0001/test/LoaderDependencyDedupTest.java b/defects/wine-0001/test/LoaderDependencyDedupTest.java new file mode 100644 index 000000000..b966a2b4f --- /dev/null +++ b/defects/wine-0001/test/LoaderDependencyDedupTest.java @@ -0,0 +1,99 @@ +import java.util.*; + +/** + * Unit test for Wine wine-0001: ntdll/loader.c find_module_dependency + * performs O(D) linear scan on a circular singly-linked list to check if a + * DLL dependency already exists before adding it. Called for every import + * during fixup_imports, giving O(I*D) per module. + * + * Fix: maintain a HashSet alongside the linked list for O(1) dedup. + * + * Defect file: dlls/ntdll/loader.c lines 860-873 + */ +public class LoaderDependencyDedupTest { + + // --- Defective: linear scan to find existing dependency --- + static class DdagNodeDefective { + List dependencies = new LinkedList<>(); + + boolean hasDependency(Object to) { + for (Object dep : dependencies) { + if (dep == to) return true; // O(D) scan + } + return false; + } + + void addDependency(Object to) { + if (!hasDependency(to)) { // O(D) per call + dependencies.add(to); + } + } + } + + // --- Fixed: hash set for O(1) dedup --- + static class DdagNodeFixed { + List dependencies = new LinkedList<>(); + Set dependencySet = new HashSet<>(); + + void addDependency(Object to) { + if (dependencySet.add(to)) { // O(1) dedup + dependencies.add(to); + } + } + } + + public static void main(String[] args) { + int N = 500; + + // Simulate modules being imported + Object[] modules = new Object[N]; + for (int i = 0; i < N; i++) modules[i] = new Object(); + + // Defective: add all, then try to add all again (worst case dedup) + DdagNodeDefective defNode = new DdagNodeDefective(); + DdagNodeFixed fixNode = new DdagNodeFixed(); + + // Correctness: both should add N unique deps + for (Object m : modules) { defNode.addDependency(m); fixNode.addDependency(m); } + assert defNode.dependencies.size() == N : "Defective size wrong"; + assert fixNode.dependencies.size() == N : "Fixed size wrong"; + + // Re-add (all duplicates) + for (Object m : modules) { defNode.addDependency(m); fixNode.addDependency(m); } + assert defNode.dependencies.size() == N : "Defective re-add size wrong"; + assert fixNode.dependencies.size() == N : "Fixed re-add size wrong"; + + // Warmup + for (int w = 0; w < 200; w++) { + DdagNodeDefective d = new DdagNodeDefective(); + DdagNodeFixed f = new DdagNodeFixed(); + for (Object m : modules) { d.addDependency(m); f.addDependency(m); } + for (Object m : modules) { d.addDependency(m); f.addDependency(m); } + } + + // Benchmark + int ITER = 500; + long t0 = System.nanoTime(); + for (int i = 0; i < ITER; i++) { + DdagNodeDefective d = new DdagNodeDefective(); + for (Object m : modules) d.addDependency(m); + for (Object m : modules) d.addDependency(m); // dedup pass + } + long defectNs = System.nanoTime() - t0; + + t0 = System.nanoTime(); + for (int i = 0; i < ITER; i++) { + DdagNodeFixed f = new DdagNodeFixed(); + for (Object m : modules) f.addDependency(m); + for (Object m : modules) f.addDependency(m); // dedup pass + } + long fixedNs = System.nanoTime() - t0; + + double ratio = (double) defectNs / fixedNs; + System.out.printf("DLL dependency dedup N=%d defect=%.1fms fixed=%.1fms ratio=%.1fx%n", + N, defectNs / 1e6, fixedNs / 1e6, ratio); + + assert ratio > 2.0 : "Expected >2x speedup, got " + ratio; + System.out.println("PASS"); + } +}