java-topology/defects/ffmpeg/patch/ffmpeg-0003.patch
russell@unturf.com 25c2bafdee undf: assign 694-720; stamp patches; ruby-0003/elixir-0002/r-source-0002/victoria-metrics-0002
New UNDF assignments (693→720):
  elixir-0002 → UNDF-2026-000000698 (typespec used_type_pairs O(T²))
  r-source-0002 → UNDF-2026-000000711 (.walkClassGraph match dedup O(S²))
  ruby-0003 → UNDF-2026-000000712 (RubyGems dependent_gems O(N²×D))
  victoria-metrics-0002 → UNDF-2026-000000717 (MetricName tag-filter O(T×I))

Total: 720 UNDF assigned
2026-03-29 22:28:31 -04:00

111 lines
3.9 KiB
Diff
Raw Permalink 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.

# UNDF: UNDF-2026-000000700
--- 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;
}