import java.util.*; /** * CWE-407 / CWE-312 simulation tests for darktable defects. * * darktable-0001: map_locations image diff via g_list_find O(N*M) * darktable-0002: _tag_add_tags_to_list dedup via g_list_find O(T*L) * darktable-0003: map view clustering sel_imgs g_list_find inside O(I*J) loop * darktable-0004: pwstorage backends log credentials verbatim (CWE-312) * darktable-0005: modulegroups test_visible O(M*G*P) per UI refresh */ public class DarktableTest { // --------------------------------------------------------------- // darktable-0001: map_locations symmetric diff O(N*M) vs O(N+M) // --------------------------------------------------------------- /** Defective: g_list_find inside loop — O(N*M) */ static int mapLocationDiffDefective(List oldImgs, List newImgs) { int ops = 0; // detach old not in new for (int id : oldImgs) { for (int nid : newImgs) { ops++; if (nid == id) break; } } // attach new not in old for (int id : newImgs) { for (int oid : oldImgs) { ops++; if (oid == id) break; } } return ops; } /** Fixed: GHashTable for O(1) lookup — O(N+M) */ static int mapLocationDiffFixed(List oldImgs, List newImgs) { int ops = 0; Set newSet = new HashSet<>(newImgs); ops += newImgs.size(); for (int id : oldImgs) { newSet.contains(id); ops++; } Set oldSet = new HashSet<>(oldImgs); ops += oldImgs.size(); for (int id : newImgs) { oldSet.contains(id); ops++; } return ops; } static void testMapLocationDiff() { int N = 1000; List oldImgs = new ArrayList<>(); List newImgs = new ArrayList<>(); for (int i = 0; i < N; i++) { oldImgs.add(i); newImgs.add(i + N / 2); } int defectOps = mapLocationDiffDefective(oldImgs, newImgs); int fixedOps = mapLocationDiffFixed(oldImgs, newImgs); double ratio = (double) defectOps / fixedOps; System.out.printf("darktable-0001 map_locations diff: defect=%d fixed=%d ratio=%.1fx%n", defectOps, fixedOps, ratio); assert ratio > 10 : "Expected >10x ratio, got " + ratio; System.out.println(" PASS"); } // --------------------------------------------------------------- // darktable-0002: tag dedup via g_list_find O(T*L) ≈ O(N²) // --------------------------------------------------------------- /** Defective: linear scan dedup */ static int tagAddToListDefective(List existingTags, List newTags) { int ops = 0; List list = new ArrayList<>(existingTags); for (int tag : newTags) { boolean found = false; for (int t : list) { ops++; if (t == tag) { found = true; break; } } if (!found) list.add(tag); } return ops; } /** Fixed: HashSet companion */ static int tagAddToListFixed(List existingTags, List newTags) { int ops = 0; Set seen = new HashSet<>(existingTags); ops += existingTags.size(); for (int tag : newTags) { ops++; if (!seen.contains(tag)) { seen.add(tag); } } return ops; } static void testTagAddToList() { int N = 500; List existing = new ArrayList<>(); List toAdd = new ArrayList<>(); // all unique — worst case for dedup for (int i = 0; i < N; i++) existing.add(i); for (int i = N; i < 2 * N; i++) toAdd.add(i); int defectOps = tagAddToListDefective(existing, toAdd); int fixedOps = tagAddToListFixed(existing, toAdd); double ratio = (double) defectOps / fixedOps; System.out.printf("darktable-0002 tag dedup: defect=%d fixed=%d ratio=%.1fx%n", defectOps, fixedOps, ratio); assert ratio > 50 : "Expected >50x ratio, got " + ratio; System.out.println(" PASS"); } // --------------------------------------------------------------- // darktable-0003: map view sel_imgs inside O(I*J) clustering loop // --------------------------------------------------------------- /** Defective: g_list_find(sel_imgs, imgid) inside nested I×J loop — O(I²×S) */ static long mapViewClusterDefective(int imgCount, List selImgs, int[] clusterIds) { long ops = 0; for (int i = 0; i < imgCount; i++) { int group = clusterIds[i]; for (int j = 0; j < imgCount; j++) { if (clusterIds[j] == group) { // linear scan of sel_imgs for (int s : selImgs) { ops++; if (s == j) break; } } } } return ops; } /** Fixed: HashSet for O(1) selection check — O(I²+S) */ static long mapViewClusterFixed(int imgCount, List selImgs, int[] clusterIds) { long ops = 0; Set selSet = new HashSet<>(selImgs); ops += selImgs.size(); for (int i = 0; i < imgCount; i++) { int group = clusterIds[i]; for (int j = 0; j < imgCount; j++) { if (clusterIds[j] == group) { selSet.contains(j); ops++; } } } return ops; } static void testMapViewCluster() { int I = 500; int S = 200; List selImgs = new ArrayList<>(); for (int i = 0; i < S; i++) selImgs.add(i); // All in one cluster — worst case int[] clusterIds = new int[I]; Arrays.fill(clusterIds, 1); long defectOps = mapViewClusterDefective(I, selImgs, clusterIds); long fixedOps = mapViewClusterFixed(I, selImgs, clusterIds); double ratio = (double) defectOps / fixedOps; System.out.printf("darktable-0003 map view cluster sel: defect=%d fixed=%d ratio=%.1fx%n", defectOps, fixedOps, ratio); assert ratio > 10 : "Expected >10x ratio, got " + ratio; System.out.println(" PASS"); } // --------------------------------------------------------------- // darktable-0004: pwstorage credential logged verbatim (CWE-312) // --------------------------------------------------------------- /** * Defective: credential value logged verbatim. * Simulates dt_print(DT_DEBUG_PWSTORAGE, "storing (%s, %s)", key, value) * where value = {"server":"...","username":"...","password":"s3cr3t"}. */ static String logCredentialDefective(String key, String credentialJson) { // Mirrors: dt_print(DT_DEBUG_PWSTORAGE, "storing (%s, %s)", key, value) return String.format("[pwstorage_kwallet_set] storing (%s, %s)", key, credentialJson); } /** * Fixed: only log the key (service name), never the value (which contains password). * Mirrors: dt_print(DT_DEBUG_PWSTORAGE, "storing (%s, [REDACTED])", key) */ static String logCredentialFixed(String key, String credentialJson) { return String.format("[pwstorage_kwallet_set] storing (%s, [REDACTED])", key); } static void testPwstorageCredentialLog() { String key = "example.com"; String credJson = "{\"server\":\"example.com\",\"username\":\"alice\",\"password\":\"s3cr3t\"}"; String defectLog = logCredentialDefective(key, credJson); String fixedLog = logCredentialFixed(key, credJson); boolean defectExposesPassword = defectLog.contains("s3cr3t"); boolean fixedExposesPassword = fixedLog.contains("s3cr3t"); System.out.printf("darktable-0004 pwstorage CWE-312: defect_exposes=%b fixed_exposes=%b%n", defectExposesPassword, fixedExposesPassword); assert defectExposesPassword : "Defective log should expose password"; assert !fixedExposesPassword : "Fixed log must NOT expose password"; assert fixedLog.contains("[REDACTED]") : "Fixed log must contain [REDACTED]"; System.out.println(" PASS"); } // --------------------------------------------------------------- // darktable-0005: modulegroups test_visible O(M*G*P) vs O(M) // --------------------------------------------------------------- /** * Defective: for each of M modules, iterate G groups, each doing linear scan of P items. * Mirrors _lib_modulegroups_test_visible called inside _lib_modulegroups_update_iop_visibility. */ static int modulegroupsTestVisibleDefective(List iopModules, List> groups) { int ops = 0; for (String module : iopModules) { // _lib_modulegroups_test_visible inner loop for (List group : groups) { for (String gm : group) { ops++; if (gm.equals(module)) break; } } } return ops; } /** * Fixed: precompute a Set of all visible module names across groups. * test_visible = O(1) per module. */ static int modulegroupsTestVisibleFixed(List iopModules, List> groups) { int ops = 0; // Rebuild visible set once (done when groups change) Set visibleSet = new HashSet<>(); for (List group : groups) { for (String gm : group) { visibleSet.add(gm); ops++; // set build cost } } // Per-update: O(M) hash lookups for (String module : iopModules) { visibleSet.contains(module); ops++; } return ops; } static void testModulegroupsTestVisible() { // 80 iop modules, 8 groups of 10 modules each int M = 80; int G = 8; int P = 10; List iopModules = new ArrayList<>(); for (int i = 0; i < M; i++) iopModules.add("module_" + i); List> groups = new ArrayList<>(); for (int g = 0; g < G; g++) { List group = new ArrayList<>(); for (int p = 0; p < P; p++) { // Distribute modules evenly across groups group.add("module_" + (g * P + p)); } groups.add(group); } int defectOps = modulegroupsTestVisibleDefective(iopModules, groups); int fixedOps = modulegroupsTestVisibleFixed(iopModules, groups); double ratio = (double) defectOps / fixedOps; System.out.printf("darktable-0005 modulegroups test_visible: defect=%d fixed=%d ratio=%.1fx%n", defectOps, fixedOps, ratio); assert ratio > 3.0 : "Expected >3x ratio, got " + ratio; System.out.println(" PASS"); } // --------------------------------------------------------------- public static void main(String[] args) { testMapLocationDiff(); testTagAddToList(); testMapViewCluster(); testPwstorageCredentialLog(); testModulegroupsTestVisible(); System.out.println("\nAll 5 darktable tests PASSED."); } }