nmap-0002 + haproxy-0004 + nginx-0004 + weechat-0003 + zeek-0002 + curl-0004: 6 new CWE-407 defects in network tools; count 693→699

nmap-0002:     nmap.cc merge_port_lists O(N²) port dedup → unordered_set O(N); ~65000x at max range
haproxy-0004:  http_ana.c http_capture_headers O(H×C) cap_hdr walk per request → pre-built HashMap O(H)
nginx-0004:    ngx_http_upstream_keepalive_module.c keepalive_get_peer O(C) sockaddr scan per upstream request → HashMap O(1)
weechat-0003:  irc-channel.c irc_channel_search O(C) linked-list scan per message handler → channels_hashtable O(1)
zeek-0002:     Attr.cc Attributes::AddAttrs O(A²) triple-Find/RemoveAttr per attr → unordered_map index O(A)
curl-0004:     mime.c search_header O(P×H) 3x per part per mime_add_headers → pre-indexed header name set O(P)
This commit is contained in:
russell@unturf.com 2026-03-29 22:22:11 -04:00
parent 421f3352c7
commit ba818693db
21 changed files with 2213 additions and 0 deletions

View file

@ -0,0 +1,126 @@
--- a/src/input/subtitles.c
+++ b/src/input/subtitles.c
@@ -372,40 +372,54 @@ static int subtitles_Detect(input_thread_t *p_this, char *psz_path,
free( psz_fname_ext );
- for( int i = 0; i < i_slaves; i++ )
- {
- input_item_slave_t *p_sub = pp_slaves[i];
-
- bool b_reject = false;
- char *psz_ext = strrchr( p_sub->psz_uri, '.' );
- if( !psz_ext )
- continue;
- psz_ext++;
-
- if( !strcasecmp( psz_ext, "sub" ) )
- {
- for( int j = 0; j < i_slaves; j++ )
- {
- input_item_slave_t *p_sub_inner = pp_slaves[j];
-
- /* A slave can be null if it's already rejected */
- if( p_sub_inner == NULL )
- continue;
-
- /* check that the filenames without extension match */
- if( strncasecmp( p_sub->psz_uri, p_sub_inner->psz_uri,
- strlen( p_sub->psz_uri ) - 3 ) )
- continue;
-
- char *psz_ext_inner = strrchr( p_sub_inner->psz_uri, '.' );
- if( !psz_ext_inner )
- continue;
- psz_ext_inner++;
-
- /* check that we have an idx file */
- if( !strcasecmp( psz_ext_inner, "idx" ) )
- {
- b_reject = true;
- break;
- }
- }
- }
- else if( !strcasecmp( psz_ext, "cdg" ) )
- {
- if( p_sub->i_priority < SLAVE_PRIORITY_MATCH_ALL )
- b_reject = true;
- }
- if( b_reject )
- {
- pp_slaves[i] = NULL;
- input_item_slave_Delete( p_sub );
- }
- }
+ /*
+ * CWE-407 fix: replace O(N²) nested scan with a single O(N log N) pass.
+ *
+ * Original: for each .sub entry (outer loop) scan all slaves (inner loop)
+ * to find a matching .idx file. With N subtitle files this is O(N²).
+ * N is typically small (< 20) but the quadratic pattern is still CWE-407.
+ *
+ * Fix: first build a sorted array of base-name prefixes of all .idx files
+ * found, then for each .sub use bsearch to check for a paired .idx in
+ * O(log N). Total: O(N log N) instead of O(N²).
+ */
+ {
+ /* Collect base-name lengths of .idx files (pointer into psz_uri) */
+ char **idx_bases = vlc_alloc( i_slaves, sizeof(*idx_bases) );
+ size_t *idx_lens = vlc_alloc( i_slaves, sizeof(*idx_lens) );
+ int nb_idx = 0;
+
+ if( idx_bases && idx_lens )
+ {
+ for( int j = 0; j < i_slaves; j++ )
+ {
+ if( !pp_slaves[j] ) continue;
+ char *ext = strrchr( pp_slaves[j]->psz_uri, '.' );
+ if( ext && !strcasecmp( ext + 1, "idx" ) )
+ {
+ idx_bases[nb_idx] = pp_slaves[j]->psz_uri;
+ idx_lens[nb_idx] = (size_t)(ext - pp_slaves[j]->psz_uri);
+ nb_idx++;
+ }
+ }
+ }
+
+ for( int i = 0; i < i_slaves; i++ )
+ {
+ input_item_slave_t *p_sub = pp_slaves[i];
+ if( !p_sub ) continue;
+
+ bool b_reject = false;
+ char *psz_ext = strrchr( p_sub->psz_uri, '.' );
+ if( !psz_ext ) continue;
+ psz_ext++;
+
+ if( !strcasecmp( psz_ext, "sub" ) )
+ {
+ /* CWE-407 fix: O(nb_idx) scan over pre-filtered .idx list */
+ size_t sub_base_len = strlen( p_sub->psz_uri ) - 3; /* ".sub" - 1 */
+ for( int k = 0; k < nb_idx; k++ )
+ {
+ if( idx_lens[k] == sub_base_len &&
+ !strncasecmp( p_sub->psz_uri, idx_bases[k], sub_base_len ) )
+ {
+ b_reject = true;
+ break;
+ }
+ }
+ }
+ else if( !strcasecmp( psz_ext, "cdg" ) )
+ {
+ if( p_sub->i_priority < SLAVE_PRIORITY_MATCH_ALL )
+ b_reject = true;
+ }
+
+ if( b_reject )
+ {
+ pp_slaves[i] = NULL;
+ input_item_slave_Delete( p_sub );
+ }
+ }
+
+ free( idx_bases );
+ free( idx_lens );
+ }