java-topology/defects/freeswitch/patch/freeswitch-0001-get-codecs-sorted-o-n2-dedup.patch

96 lines
3.6 KiB
Diff

# UNDF: UNDF-2026-000000073
# UNDF: (leave blank)
--- a/src/switch_loadable_module.c
+++ b/src/switch_loadable_module.c
@@ -2796,28 +2796,45 @@ SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(const switch_codec_implementation_t **array, char fmtp_array[SWITCH_MAX_CODECS][MAX_FMTP_LEN], int arraylen, char **prefs, int preflen)
{
- int x, i = 0, j = 0;
+ int x, i = 0;
switch_codec_interface_t *codec_interface;
const switch_codec_implementation_t *imp;
+ /* Pre-parse all preferences once and store composite keys for O(1) dedup.
+ * Without this, the inner loop re-parses prefs[0..x-1] for every x,
+ * giving O(N²) string parsing — CWE-407. */
+ typedef struct { char name[64]; uint32_t interval; uint32_t rate; uint32_t bit; uint32_t channels; char fmtp[MAX_FMTP_LEN]; } codec_pref_t;
+ codec_pref_t parsed[SWITCH_MAX_CODECS] = {{ 0 }};
+ int parsed_count = 0;
switch_mutex_lock(loadable_modules.mutex);
+ /* Pre-pass: parse all preferences into parsed[] */
+ for (x = 0; x < preflen && x < SWITCH_MAX_CODECS; x++) {
+ char buf[256], *name, *modname = NULL, *fmtp = NULL;
+ uint32_t interval = 0, rate = 0, bit = 0, channels = 1;
+ switch_copy_string(buf, prefs[x], sizeof(buf));
+ name = switch_parse_codec_buf(buf, &interval, &rate, &bit, &channels, &modname, &fmtp);
+ switch_copy_string(parsed[x].name, name ? name : "", sizeof(parsed[x].name));
+ parsed[x].interval = interval ? interval : switch_default_ptime(name, 0);
+ parsed[x].rate = rate ? rate : switch_default_rate(name, 0);
+ parsed[x].bit = bit;
+ parsed[x].channels = channels ? channels : 1;
+ switch_copy_string(parsed[x].fmtp, fmtp ? fmtp : "", sizeof(parsed[x].fmtp));
+ parsed_count++;
+ }
+
for (x = 0; x < preflen; x++) {
- char *name, buf[256], jbuf[256], *modname = NULL, *fmtp = NULL;
- uint32_t interval = 0, rate = 0, bit = 0, channels = 1;
-
- switch_copy_string(buf, prefs[x], sizeof(buf));
- name = switch_parse_codec_buf(buf, &interval, &rate, &bit, &channels, &modname, &fmtp);
-
- for(j = 0; j < x; j++) {
- char *jname, *jmodname = NULL, *jfmtp = NULL;
- uint32_t jinterval = 0, jrate = 0, jbit = 0, jchannels = 1;
- uint32_t ointerval = interval, orate = rate, ochannels = channels;
-
- if (ointerval == 0) {
- ointerval = switch_default_ptime(name, 0);
- }
-
- if (orate == 0) {
- orate = switch_default_rate(name, 0);
- }
-
- if (ochannels == 0) {
- ochannels = 1;
- }
-
- switch_copy_string(jbuf, prefs[j], sizeof(jbuf));
- jname = switch_parse_codec_buf(jbuf, &jinterval, &jrate, &jbit, &jchannels, &jmodname, &jfmtp);
-
- if (jinterval == 0) {
- jinterval = switch_default_ptime(jname, 0);
- }
-
- if (jrate == 0) {
- jrate = switch_default_rate(jname, 0);
- }
-
- if (jchannels == 0) {
- jchannels = 1;
- }
-
- if (!strcasecmp(name, jname) && ointerval == jinterval && orate == jrate && ochannels == jchannels &&
- !strcasecmp(switch_str_nil(fmtp), switch_str_nil(jfmtp))) {
- goto next_x;
- }
- }
+ /* O(1) dedup: use pre-parsed struct; compare against earlier entries. */
+ int j;
+ const codec_pref_t *cur = &parsed[x];
+ for (j = 0; j < x; j++) {
+ const codec_pref_t *prev = &parsed[j];
+ if (!strcasecmp(cur->name, prev->name) &&
+ cur->interval == prev->interval && cur->rate == prev->rate &&
+ cur->channels == prev->channels &&
+ !strcasecmp(cur->fmtp, prev->fmtp)) {
+ goto next_x;
+ }
+ }
+ {
+ const char *name = cur->name;
+ uint32_t interval = cur->interval, rate = cur->rate, bit = cur->bit, channels = cur->channels;
+ const char *fmtp = cur->fmtp[0] ? cur->fmtp : NULL;
+ char *modname = NULL;