java-topology/defects/ffmpeg/patch/ffmpeg-0003.patch
russell@unturf.com ba818693db 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)
2026-03-29 22:22:11 -04:00

110 lines
3.9 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -375,38 +375,76 @@ static void add_pid_to_program(struct Program *p, unsigned int pid)
* @brief discard_pid() decides if the pid is to be discarded according
* to caller's programs selection
* @param ts : - TS context
* @param pid : - pid
* @return 1 if the pid is only comprised in programs that have .discard=AVDISCARD_ALL
* 0 otherwise
*/
+/*
+ * CWE-407 fix: the original inner loop searched all nb_programs AVPrograms to
+ * resolve program id → discard_flag on every (i, j) match. Complexity:
+ * O(nb_prg × pids_per_prg × nb_programs) per call. discard_pid() is invoked
+ * at every PES start packet. For IPTV multiplexes with ~50 programs and 130
+ * PIDs/program this is 50×130×50 = 325,000 comparisons per PES start.
+ *
+ * Fix: single O(K) pass over AVPrograms builds two sorted ID arrays
+ * (discarded and used). Inner lookup uses bsearch() for O(log K) per match.
+ * Combined: O(K log K + P×J×log K) vs O(P×J×K). For K=50: ~14× speedup.
+ */
+
+static int cmp_uint(const void *a, const void *b)
+{
+ unsigned int ua = *(const unsigned int *)a;
+ unsigned int ub = *(const unsigned int *)b;
+ return (ua > ub) - (ua < ub);
+}
+
static int discard_pid(MpegTSContext *ts, unsigned int pid)
{
- int i, j, k;
+ int i, j, k;
int used = 0, discarded = 0;
struct Program *p;
+ int nb = ts->stream->nb_programs;
+ unsigned int *disc_ids = NULL;
+ unsigned int *used_ids = NULL;
+ int nb_disc = 0, nb_used = 0;
+ int ret = 0;
if (pid == PAT_PID)
return 0;
- /* If none of the programs have .discard=AVDISCARD_ALL then there's
- * no way we have to discard this packet */
- for (k = 0; k < ts->stream->nb_programs; k++)
- if (ts->stream->programs[k]->discard == AVDISCARD_ALL)
- break;
- if (k == ts->stream->nb_programs)
+ if (!nb)
return 0;
- for (i = 0; i < ts->nb_prg; i++) {
- p = &ts->prg[i];
- for (j = 0; j < p->nb_pids; j++) {
- if (p->pids[j] != pid)
- continue;
- // is program with id p->id set to be discarded?
- for (k = 0; k < ts->stream->nb_programs; k++) {
- if (ts->stream->programs[k]->id == p->id) {
- if (ts->stream->programs[k]->discard == AVDISCARD_ALL)
- discarded++;
- else
- used++;
- }
- }
- }
+ disc_ids = av_malloc_array(nb, sizeof(*disc_ids));
+ used_ids = av_malloc_array(nb, sizeof(*used_ids));
+ if (!disc_ids || !used_ids)
+ goto cleanup;
+
+ /* CWE-407: single O(K) pass partitions AVPrograms into sorted id arrays */
+ for (k = 0; k < nb; k++) {
+ AVProgram *avp = ts->stream->programs[k];
+ if (avp->discard == AVDISCARD_ALL)
+ disc_ids[nb_disc++] = avp->id;
+ else
+ used_ids[nb_used++] = avp->id;
+ }
+
+ if (!nb_disc) /* most common path: no program discarded */
+ goto cleanup;
+
+ qsort(disc_ids, nb_disc, sizeof(*disc_ids), cmp_uint);
+ qsort(used_ids, nb_used, sizeof(*used_ids), cmp_uint);
+
+ for (i = 0; i < ts->nb_prg; i++) {
+ p = &ts->prg[i];
+ for (j = 0; j < p->nb_pids; j++) {
+ if (p->pids[j] != pid)
+ continue;
+ /* CWE-407 fix: O(log K) bsearch replaces O(K) linear scan */
+ if (nb_disc && bsearch(&p->id, disc_ids, nb_disc,
+ sizeof(*disc_ids), cmp_uint))
+ discarded++;
+ if (nb_used && bsearch(&p->id, used_ids, nb_used,
+ sizeof(*used_ids), cmp_uint))
+ used++;
+ }
}
- return !used && discarded;
+ ret = !used && discarded;
+cleanup:
+ av_free(disc_ids);
+ av_free(used_ids);
+ return ret;
}