kdenlive: all 5 MOADs scanned. - MOAD-0001: 8 pre-existing CWE-407 patches confirmed, no new sites found. - MOAD-0002: pCore god object (3704 refs) noted as Intertangle observation. - MOAD-0003: CLEAN (thread_local is execution guard, not request identity). - MOAD-0004: CLEAN (no credential logging). - MOAD-0005 NEW: buildLumaThumbs() called via QtConcurrent::run() writes to MainWindow::m_lumacache (QMap, not thread-safe) without mutex while UI widgets read/write the same map from the main thread — data race on project load. Patch: add QMutex, wrap all m_lumacache access sites. audacity: all 5 MOADs scanned. - MOAD-0001: 2 pre-existing CWE-407 patches confirmed, no new sites found. - MOAD-0002 through MOAD-0005: CLEAN. 9/9 KdenliveTest PASS (added kdenlive-0009 MOAD-0005 threading test).
144 lines
4.3 KiB
Java
144 lines
4.3 KiB
Java
package unit;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
|
|
/**
|
|
* CWE-407 unit test: gstreamer-0005 — WebRTC seen_transceivers O(T²) → O(T)
|
|
*
|
|
* Models _create_offer_task() in
|
|
* subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c
|
|
*
|
|
* The function tracks which transceivers have already been assigned to
|
|
* an SDP m-line via a GList *seen_transceivers. Multiple loops iterate
|
|
* over all T transceivers and call g_list_find(seen_transceivers, trans)
|
|
* (O(T) per call). The full function is O(T^2).
|
|
*
|
|
* Fix: replace GList with GHashTable (g_direct_hash / g_direct_equal)
|
|
* for O(1) contains/add operations, reducing the full function to O(T).
|
|
*
|
|
* Parameters: T = number of transceivers (audio+video streams).
|
|
* For a 25-participant WebRTC conference: T = 50 (25a + 25v).
|
|
* Expected ratio: >20x op-count reduction at T=100.
|
|
*/
|
|
public class Gstreamer0005WebrtcSeenTransceiversTest {
|
|
|
|
static long slowOps = 0;
|
|
static long fastOps = 0;
|
|
|
|
/**
|
|
* Slow: GList-style seen-set — O(T) membership check.
|
|
* Simulates g_list_find(seen_transceivers, trans).
|
|
*/
|
|
static boolean listContains(List<Integer> seen, int trans) {
|
|
for (int s : seen) {
|
|
slowOps++;
|
|
if (s == trans) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Slow simulation of _create_offer_task seen_transceivers loops.
|
|
*
|
|
* Three passes over T transceivers each calling g_list_find:
|
|
* Pass 1: renegotiation loop (inner j-loop over T, find on grown list)
|
|
* Pass 2: gather existing mids loop (T iterations, find check)
|
|
* Pass 3: add extra streams loop (T iterations, find check)
|
|
*
|
|
* Total: O(T) inserts + O(T^2) finds = O(T^2)
|
|
*/
|
|
static void createOfferSlow(int T) {
|
|
List<Integer> seen = new ArrayList<>();
|
|
|
|
// Pass 1: renegotiation — inner loop T finds on partially-filled list
|
|
for (int i = 0; i < T; i++) {
|
|
for (int j = 0; j < T; j++) {
|
|
if (listContains(seen, j)) continue;
|
|
// only add first match per outer i
|
|
seen.add(j);
|
|
break;
|
|
}
|
|
}
|
|
|
|
seen.clear();
|
|
|
|
// Pass 2: gather mids — T iterations, each O(T) find
|
|
for (int i = 0; i < T; i++) {
|
|
if (listContains(seen, i)) continue;
|
|
}
|
|
|
|
// Pass 3: add extra streams — T iterations, each O(T) find
|
|
for (int i = 0; i < T; i++) {
|
|
if (!listContains(seen, i)) {
|
|
seen.add(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fast simulation using HashSet — O(1) contains/add.
|
|
* Simulates g_hash_table_contains + g_hash_table_add.
|
|
*/
|
|
static void createOfferFast(int T) {
|
|
Set<Integer> seen = new HashSet<>();
|
|
|
|
// Pass 1: renegotiation
|
|
for (int i = 0; i < T; i++) {
|
|
for (int j = 0; j < T; j++) {
|
|
fastOps++;
|
|
if (seen.contains(j)) continue;
|
|
seen.add(j);
|
|
break;
|
|
}
|
|
}
|
|
|
|
seen.clear();
|
|
|
|
// Pass 2: gather mids
|
|
for (int i = 0; i < T; i++) {
|
|
fastOps++;
|
|
if (seen.contains(i)) continue;
|
|
}
|
|
|
|
// Pass 3: add extra streams
|
|
for (int i = 0; i < T; i++) {
|
|
fastOps++;
|
|
if (!seen.contains(i)) {
|
|
seen.add(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void main(String[] args) {
|
|
final int T = 100; // 50 audio + 50 video transceivers
|
|
|
|
// Warm up
|
|
createOfferSlow(10);
|
|
createOfferFast(10);
|
|
slowOps = 0;
|
|
fastOps = 0;
|
|
|
|
// Measure
|
|
createOfferSlow(T);
|
|
long measuredSlowOps = slowOps;
|
|
|
|
createOfferFast(T);
|
|
long measuredFastOps = fastOps;
|
|
|
|
double ratio = (double) measuredSlowOps / measuredFastOps;
|
|
|
|
System.out.printf("gstreamer-0005 WebRTC seen_transceivers O(T^2) vs O(T)%n");
|
|
System.out.printf(" T=%d transceivers%n", T);
|
|
System.out.printf(" slow ops (GList find): %d%n", measuredSlowOps);
|
|
System.out.printf(" fast ops (GHashTable): %d%n", measuredFastOps);
|
|
System.out.printf(" ratio: %.1fx%n", ratio);
|
|
|
|
assert ratio > 10.0 :
|
|
"Expected >10x ratio at T=" + T + ", got " + ratio;
|
|
|
|
System.out.println("PASS");
|
|
}
|
|
}
|