import java.util.*; /** * CWE-407 simulation for Shotcut defects. * shotcut-0001: PlaylistProxyModel m_hashes vector std::find in filterAcceptsRow */ public class ShotcutTest { // --- shotcut-0001: m_hashes linear find per playlist row --- static long playlistHashesDefect(int N) { // Build m_hashes vector with N/2 unique hashes (simulating timeline clips) List hashes = new ArrayList<>(); for (int i = 0; i < N / 2; i++) { hashes.add("hash-" + i); } long ops = 0; // filterAcceptsRow called for each of N playlist rows for (int row = 0; row < N; row++) { String hash = "hash-" + (row % N); // std::find linear scan for (String h : hashes) { ops++; if (h.equals(hash)) break; } } return ops; } static long playlistHashesFixed(int N) { Set hashes = new HashSet<>(); for (int i = 0; i < N / 2; i++) { hashes.add("hash-" + i); } long ops = 0; for (int row = 0; row < N; row++) { ops++; String hash = "hash-" + (row % N); hashes.contains(hash); } return ops; } public static void main(String[] args) { int pass = 0, fail = 0; // Test shotcut-0001: playlist N=1000 { long defectOps = playlistHashesDefect(1000); long fixedOps = playlistHashesFixed(1000); double ratio = (double) defectOps / fixedOps; boolean ok = ratio > 50.0; System.out.printf("shotcut-0001 m_hashes filterAcceptsRow: defect=%d fixed=%d ratio=%.1fx %s%n", defectOps, fixedOps, ratio, ok ? "PASS" : "FAIL"); if (ok) pass++; else fail++; } System.out.printf("%nSummary: %d/%d PASS%n", pass, pass + fail); if (fail > 0) System.exit(1); } }