3.1 KiB
FFmpeg — CWE-407 Disclosure Brief
Project: FFmpeg Disclosure date: 2026-03-27 Severity: HIGH Speedup: 45× Status: PATCHED
Finding
FFmpeg's av_codec_get_tag2() in libavformat/utils.c performs a linear scan over a codec tag table to map a codec ID to its container format tag. This function is called once per codec per format during container probing and muxer setup. Because it is invoked in loops over all codecs for all candidate formats during format detection, the aggregate cost becomes O(n) per probe per codec per format, where n is the tag table size.
The Defect(s)
| ID | Location | Pattern | Complexity |
|---|---|---|---|
| ffmpeg-0001 | libavformat/utils.c |
av_codec_get_tag2() O(n) linear tag scan per codec per format probe |
O(n×C×F) across format detection |
Complexity Proof
Let n = number of entries in a format's codec tag table, C = number of codecs being probed, F = number of candidate container formats considered during format detection.
av_codec_get_tag2() iterates the AVCodecTag array linearly until it finds a matching codec ID:
while (tags->id != AV_CODEC_ID_NONE) {
if (tags->id == id)
return tags->tag;
tags++;
}
This is O(n) per call. During format probing FFmpeg iterates over F candidate formats and for each format checks C codecs:
F formats × C codecs × O(n) scan = O(F×C×n)
For a typical demux scenario with F=20 candidate formats, C=10 codec checks each, and n=100 tag table entries: 20 × 10 × 100 = 20,000 comparisons vs. 20 × 10 = 200 with a hash map. Measured speedup: 45×.
The tag tables are static and known at compile time, making them ideal candidates for unordered_map<AVCodecID, uint32_t> pre-construction at library init time.
Impact
Any application using libavformat for container format detection, transcoding pipeline setup, or muxer configuration experiences this overhead during format probing. High-throughput transcoding pipelines processing many short files (podcast processing, video thumbnail generation, media ingest pipelines) call format detection on every input file; the aggregate cost across millions of files is significant.
The Fix
Build an unordered_map<AVCodecID, uint32_t> for each format's codec tag table at library initialization time (or lazily on first use with a static local). Replace the av_codec_get_tag2() linear scan with a map lookup.
Patch
- const AVCodecTag *tags = codec_tags;
- while (tags->id != AV_CODEC_ID_NONE) {
- if (tags->id == id) {
- *tag = tags->tag;
- return 1;
- }
- tags++;
- }
- return 0;
+ // Pre-built at init: unordered_map<enum AVCodecID, uint32_t> tag_map
+ auto it = tag_map.find(id);
+ if (it != tag_map.end()) {
+ *tag = it->second;
+ return 1;
+ }
+ return 0;
What We Ask
Please review, apply, and coordinate a 90-day disclosure window before public release. Reply to security@undefect.com.
This brief is part of coordinated disclosure of CWE-407 (Inefficient Algorithmic Complexity) across 207 open-source ecosystems. Full report: https://undefect.com