java-topology/defects/jitsi-videobridge/patch/0003-conference-speech-activity-hashset-contains.patch

34 lines
2.3 KiB
Diff

# UNDF: UNDF-2026-000000129
diff --git a/jvb/src/main/java/org/jitsi/videobridge/ConferenceSpeechActivity.java b/jvb/src/main/java/org/jitsi/videobridge/ConferenceSpeechActivity.java
index 1234567..abcdef0 100644
--- a/jvb/src/main/java/org/jitsi/videobridge/ConferenceSpeechActivity.java
+++ b/jvb/src/main/java/org/jitsi/videobridge/ConferenceSpeechActivity.java
@@ -318,14 +318,18 @@ public class ConferenceSpeechActivity
synchronized (syncRoot)
{
// Remove any endpoints we have that are no longer in the conference
+ // CWE-407 fix: pre-build HashSet for O(1) membership tests below.
+ // Line 326: conferenceEndpoints.contains() was O(n) called inside removeIf (O(n) per element → O(n²))
+ // Line 331: endpointsBySpeechActivity.contains() was O(n) per conference endpoint → O(n²)
+ // Fix: use a HashSet for conferenceEndpoints AND a LinkedHashSet for endpointsBySpeechActivity.
+ Set<AbstractEndpoint> conferenceSet = new HashSet<>(conferenceEndpoints);
+ // Rebuild as LinkedHashSet to make the contains() check at line 331 O(1) while preserving order
+ LinkedHashSet<AbstractEndpoint> activitySet = new LinkedHashSet<>(endpointsBySpeechActivity);
+
AbstractEndpoint previousDominantSpeaker
= endpointsBySpeechActivity.isEmpty() ? null : endpointsBySpeechActivity.get(0);
- endpointsListChanged = endpointsBySpeechActivity.removeIf(ep -> !conferenceEndpoints.contains(ep));
+ endpointsListChanged = endpointsBySpeechActivity.removeIf(ep -> !conferenceSet.contains(ep));
+ activitySet.retainAll(conferenceSet);
recentSpeakersChanged = recentSpeakers.removeAllExcept(conferenceEndpoints);
// Add any endpoints from the conf we don't have to the end of our list
for (AbstractEndpoint conferenceEndpoint : conferenceEndpoints)
{
- if (!endpointsBySpeechActivity.contains(conferenceEndpoint))
+ if (!activitySet.contains(conferenceEndpoint))
{
endpointsBySpeechActivity.add(conferenceEndpoint);
+ activitySet.add(conferenceEndpoint);
endpointsListChanged = true;
}
}