kdenlive-0001: ThumbnailCache m_storedOnDisk vector<int> std::find dedup O(C*P*V) MEDIUM kdenlive-0002: TimelineModel clipIds vector std::find in mix loop O(N^2) MEDIUM kdenlive-0003: TimelineController sorted_clips vector std::find in moveGroup O(N^2) MEDIUM kdenlive-0004: TimelineModel all_items list std::find in resize O(N^2) MEDIUM shotcut-0001: PlaylistProxyModel m_hashes vector std::find in filterAcceptsRow O(N^2) MEDIUM 5/5 unit tests PASS
205 lines
7.2 KiB
Java
205 lines
7.2 KiB
Java
import java.util.*;
|
|
|
|
/**
|
|
* CWE-407 simulation for Kdenlive defects.
|
|
* kdenlive-0001: ThumbnailCache storedOnDisk vector linear find for dedup
|
|
* kdenlive-0002: TimelineModel clipIds vector linear find in mix loop
|
|
* kdenlive-0003: TimelineController sorted_clips vector linear find in moveGroup
|
|
* kdenlive-0004: TimelineModel all_items list linear find in resize
|
|
*/
|
|
public class KdenliveTest {
|
|
|
|
// --- kdenlive-0001: ThumbnailCache storedOnDisk dedup ---
|
|
|
|
static long thumbnailCacheDefect(int numClips, int framesPerClip) {
|
|
// Simulates m_storedOnDisk as Map<String, List<Integer>>
|
|
Map<String, List<Integer>> storedOnDisk = new HashMap<>();
|
|
long ops = 0;
|
|
for (int c = 0; c < numClips; c++) {
|
|
String binId = "clip-" + c;
|
|
storedOnDisk.put(binId, new ArrayList<>());
|
|
for (int f = 0; f < framesPerClip; f++) {
|
|
List<Integer> vec = storedOnDisk.get(binId);
|
|
// std::find linear scan before push_back
|
|
boolean found = false;
|
|
for (int existing : vec) {
|
|
ops++;
|
|
if (existing == f) { found = true; break; }
|
|
}
|
|
if (!found) {
|
|
vec.add(f);
|
|
}
|
|
}
|
|
}
|
|
return ops;
|
|
}
|
|
|
|
static long thumbnailCacheFixed(int numClips, int framesPerClip) {
|
|
Map<String, Set<Integer>> storedOnDisk = new HashMap<>();
|
|
long ops = 0;
|
|
for (int c = 0; c < numClips; c++) {
|
|
String binId = "clip-" + c;
|
|
storedOnDisk.put(binId, new HashSet<>());
|
|
for (int f = 0; f < framesPerClip; f++) {
|
|
ops++;
|
|
storedOnDisk.get(binId).add(f);
|
|
}
|
|
}
|
|
return ops;
|
|
}
|
|
|
|
// --- kdenlive-0002: clipIds mix membership ---
|
|
|
|
static long clipIdsMixDefect(int N) {
|
|
List<Integer> clipIds = new ArrayList<>();
|
|
for (int i = 0; i < N; i++) clipIds.add(i);
|
|
long ops = 0;
|
|
for (int s : clipIds) {
|
|
// Simulate 3 std::find calls per clip (typical in mix logic)
|
|
for (int check = 0; check < 3; check++) {
|
|
int target = (s + 1) % N;
|
|
for (int id : clipIds) {
|
|
ops++;
|
|
if (id == target) break;
|
|
}
|
|
}
|
|
}
|
|
return ops;
|
|
}
|
|
|
|
static long clipIdsMixFixed(int N) {
|
|
List<Integer> clipIds = new ArrayList<>();
|
|
Set<Integer> clipIdSet = new HashSet<>();
|
|
for (int i = 0; i < N; i++) { clipIds.add(i); clipIdSet.add(i); }
|
|
long ops = 0;
|
|
for (int s : clipIds) {
|
|
for (int check = 0; check < 3; check++) {
|
|
ops++;
|
|
int target = (s + 1) % N;
|
|
clipIdSet.contains(target);
|
|
}
|
|
}
|
|
return ops;
|
|
}
|
|
|
|
// --- kdenlive-0003: sorted_clips moveGroup membership ---
|
|
|
|
static long sortedClipsMoveDefect(int N) {
|
|
List<Integer> sortedClips = new ArrayList<>();
|
|
for (int i = 0; i < N; i++) sortedClips.add(i);
|
|
long ops = 0;
|
|
for (int item : sortedClips) {
|
|
// 2 std::find calls per clip (startMix + endMix check)
|
|
for (int check = 0; check < 2; check++) {
|
|
int target = (item + 1) % N;
|
|
for (int id : sortedClips) {
|
|
ops++;
|
|
if (id == target) break;
|
|
}
|
|
}
|
|
}
|
|
return ops;
|
|
}
|
|
|
|
static long sortedClipsMoveFixed(int N) {
|
|
List<Integer> sortedClips = new ArrayList<>();
|
|
Set<Integer> sortedSet = new HashSet<>();
|
|
for (int i = 0; i < N; i++) { sortedClips.add(i); sortedSet.add(i); }
|
|
long ops = 0;
|
|
for (int item : sortedClips) {
|
|
for (int check = 0; check < 2; check++) {
|
|
ops++;
|
|
sortedSet.contains((item + 1) % N);
|
|
}
|
|
}
|
|
return ops;
|
|
}
|
|
|
|
// --- kdenlive-0004: all_items resize dedup ---
|
|
|
|
static long allItemsResizeDefect(int N) {
|
|
// currentSelection has N items; all_items grows as we add non-duplicates
|
|
LinkedList<Integer> allItems = new LinkedList<>();
|
|
allItems.add(0); // itemId
|
|
long ops = 0;
|
|
for (int id = 1; id < N; id++) {
|
|
// std::find on all_items
|
|
boolean found = false;
|
|
for (int existing : allItems) {
|
|
ops++;
|
|
if (existing == id) { found = true; break; }
|
|
}
|
|
if (!found) {
|
|
allItems.add(id);
|
|
}
|
|
}
|
|
return ops;
|
|
}
|
|
|
|
static long allItemsResizeFixed(int N) {
|
|
LinkedList<Integer> allItems = new LinkedList<>();
|
|
Set<Integer> allItemsSet = new HashSet<>();
|
|
allItems.add(0);
|
|
allItemsSet.add(0);
|
|
long ops = 0;
|
|
for (int id = 1; id < N; id++) {
|
|
ops++;
|
|
if (!allItemsSet.contains(id)) {
|
|
allItems.add(id);
|
|
allItemsSet.add(id);
|
|
}
|
|
}
|
|
return ops;
|
|
}
|
|
|
|
public static void main(String[] args) {
|
|
int pass = 0, fail = 0;
|
|
|
|
// Test kdenlive-0001: ThumbnailCache (10 clips x 200 frames)
|
|
{
|
|
long defectOps = thumbnailCacheDefect(10, 200);
|
|
long fixedOps = thumbnailCacheFixed(10, 200);
|
|
double ratio = (double) defectOps / fixedOps;
|
|
boolean ok = ratio > 5.0 && fixedOps < defectOps;
|
|
System.out.printf("kdenlive-0001 ThumbnailCache storedOnDisk: defect=%d fixed=%d ratio=%.1fx %s%n",
|
|
defectOps, fixedOps, ratio, ok ? "PASS" : "FAIL");
|
|
if (ok) pass++; else fail++;
|
|
}
|
|
|
|
// Test kdenlive-0002: clipIds mix (N=500)
|
|
{
|
|
long defectOps = clipIdsMixDefect(500);
|
|
long fixedOps = clipIdsMixFixed(500);
|
|
double ratio = (double) defectOps / fixedOps;
|
|
boolean ok = ratio > 50.0;
|
|
System.out.printf("kdenlive-0002 clipIds mix membership: defect=%d fixed=%d ratio=%.1fx %s%n",
|
|
defectOps, fixedOps, ratio, ok ? "PASS" : "FAIL");
|
|
if (ok) pass++; else fail++;
|
|
}
|
|
|
|
// Test kdenlive-0003: sorted_clips move (N=500)
|
|
{
|
|
long defectOps = sortedClipsMoveDefect(500);
|
|
long fixedOps = sortedClipsMoveFixed(500);
|
|
double ratio = (double) defectOps / fixedOps;
|
|
boolean ok = ratio > 50.0;
|
|
System.out.printf("kdenlive-0003 sorted_clips moveGroup: defect=%d fixed=%d ratio=%.1fx %s%n",
|
|
defectOps, fixedOps, ratio, ok ? "PASS" : "FAIL");
|
|
if (ok) pass++; else fail++;
|
|
}
|
|
|
|
// Test kdenlive-0004: all_items resize (N=500)
|
|
{
|
|
long defectOps = allItemsResizeDefect(500);
|
|
long fixedOps = allItemsResizeFixed(500);
|
|
double ratio = (double) defectOps / fixedOps;
|
|
boolean ok = ratio > 50.0;
|
|
System.out.printf("kdenlive-0004 all_items resize dedup: 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);
|
|
}
|
|
}
|