clickhouse-java/freeswitch: CWE-407 findings
clickhouse-java-0001: ClickHouseLoadBalancingPolicy nodes/faultyNodes LinkedList.contains O(N*F) per node selection — fix: LinkedHashSet O(1). 120x speedup at F=500 faulty nodes. freeswitch-0001: switch_loadable_module_get_codecs_sorted re-parses prefs[0..x-1] inside O(N^2) dedup loop — fix: pre-parse once O(N), then compare pre-parsed structs. 13x speedup at N=50 (SWITCH_MAX_CODECS).
This commit is contained in:
parent
ac7030d9a7
commit
e9b981a309
4 changed files with 379 additions and 249 deletions
|
|
@ -0,0 +1,95 @@
|
|||
# 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;
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue