104 lines
4.4 KiB
Diff
104 lines
4.4 KiB
Diff
# UNDF: UNDF-2026-000000073
|
|
diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c
|
|
index 1234567..abcdef0 100644
|
|
--- a/src/mod/applications/mod_conference/mod_conference.c
|
|
+++ b/src/mod/applications/mod_conference/mod_conference.c
|
|
@@ -612,6 +612,58 @@ static void conference_loop_output(conference_obj_t *conference)
|
|
/* Create write frame once per member who is not deaf for each sample in the main frame */
|
|
for (omember = conference->members; omember; omember = omember->next) {
|
|
switch_size_t ok = 1;
|
|
+
|
|
+/*
|
|
+ * CWE-407 fix: Pre-compute relationship exclusion matrix outside the per-sample loop.
|
|
+ *
|
|
+ * Original code scanned imember->relationships (linked list, O(R)) and omember->relationships (O(R))
|
|
+ * for EVERY sample of EVERY (omember, imember) pair — O(S * M * M * R) per mix cycle.
|
|
+ *
|
|
+ * Fix: before the per-sample loop for this omember, build a bitmask of imembers whose audio
|
|
+ * should be excluded for this omember. One O(M*R) pass replaces O(S*M*R) per omember.
|
|
+ *
|
|
+ * Implementation uses switch_core stack allocation (conference->member_count bounded).
|
|
+ * relationship_total guard is preserved — skip if no relationships exist.
|
|
+ */
|
|
+
|
|
+ /* --- BEGIN relationship pre-computation --- */
|
|
+ /* exclude_audio[imember->id % MAX_MEMBERS] set → omember should not hear imember */
|
|
+#define CONF_MAX_MEMBERS 512
|
|
+ uint8_t exclude_audio[CONF_MAX_MEMBERS];
|
|
+ memset(exclude_audio, 0, sizeof(exclude_audio));
|
|
+
|
|
+ if (conference->relationship_total) {
|
|
+ conference_member_t *im2;
|
|
+ for (im2 = conference->members; im2; im2 = im2->next) {
|
|
+ if (im2 == omember) continue;
|
|
+ if (!conference_utils_member_test_flag(im2, MFLAG_HAS_AUDIO)) continue;
|
|
+
|
|
+ conference_relationship_t *rel;
|
|
+ switch_size_t found = 0;
|
|
+ /* Check im2 → omember: can im2 speak to omember? */
|
|
+ for (rel = im2->relationships; rel; rel = rel->next) {
|
|
+ if ((rel->id == omember->id || rel->id == 0) && !switch_test_flag(rel, RFLAG_CAN_SPEAK)) {
|
|
+ exclude_audio[im2->id % CONF_MAX_MEMBERS] = 1;
|
|
+ found = 1;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (!found) {
|
|
+ /* Check omember → im2: can omember hear im2? */
|
|
+ for (rel = omember->relationships; rel; rel = rel->next) {
|
|
+ if ((rel->id == im2->id || rel->id == 0) && !switch_test_flag(rel, RFLAG_CAN_HEAR)) {
|
|
+ exclude_audio[im2->id % CONF_MAX_MEMBERS] = 1;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /* --- END relationship pre-computation --- */
|
|
|
|
if (!conference_utils_member_test_flag(omember, MFLAG_RUNNING) ||
|
|
(!conference_utils_member_test_flag(omember, MFLAG_NOCHANNEL) && !switch_channel_test_flag(omember->channel, CF_AUDIO))) {
|
|
@@ -641,24 +693,15 @@ static void conference_loop_output(conference_obj_t *conference)
|
|
z -= (int32_t) bptr[x];
|
|
}
|
|
|
|
- /* when there are relationships, we have to do more work by scouring all the members to see if there are any
|
|
- reasons why we should not be hearing a particular member, and if not, delete their samples as well.
|
|
- */
|
|
- if (conference->relationship_total) {
|
|
- for (imember = conference->members; imember; imember = imember->next) {
|
|
- if (imember != omember && conference_utils_member_test_flag(imember, MFLAG_HAS_AUDIO)) {
|
|
- conference_relationship_t *rel;
|
|
- switch_size_t found = 0;
|
|
- int16_t *rptr = (int16_t *) imember->frame;
|
|
- for (rel = imember->relationships; rel; rel = rel->next) {
|
|
- if ((rel->id == omember->id || rel->id == 0) && !switch_test_flag(rel, RFLAG_CAN_SPEAK)) {
|
|
- z -= (int32_t) rptr[x];
|
|
- found = 1;
|
|
- break;
|
|
- }
|
|
- }
|
|
- if (!found) {
|
|
- for (rel = omember->relationships; rel; rel = rel->next) {
|
|
- if ((rel->id == imember->id || rel->id == 0) && !switch_test_flag(rel, RFLAG_CAN_HEAR)) {
|
|
- z -= (int32_t) rptr[x];
|
|
- break;
|
|
- }
|
|
- }
|
|
- }
|
|
- }
|
|
- }
|
|
- }
|
|
+ /* CWE-407 fix: use pre-computed exclude matrix — O(1) lookup per (omember, imember) per sample */
|
|
+ if (conference->relationship_total) {
|
|
+ for (imember = conference->members; imember; imember = imember->next) {
|
|
+ if (imember != omember && conference_utils_member_test_flag(imember, MFLAG_HAS_AUDIO)) {
|
|
+ if (exclude_audio[imember->id % CONF_MAX_MEMBERS]) {
|
|
+ int16_t *rptr = (int16_t *) imember->frame;
|
|
+ z -= (int32_t) rptr[x];
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
|
|
/* Now we can convert to 16 bit. */
|