96 lines
3.6 KiB
Diff
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;
|
|
|