Add 88 new defect entries to HIGH and MEDIUM tables:
HIGH: mysql-0001/0002, mariadb-0001, redis-0001/0002, valkey-0001/0002, openvpn-0001,
vlc-0001, prometheus-0001, otel-collector-0001, cockroachdb-0001..0004,
tidb-0001..0008, kubernetes-0001/0002, go-0001, kotlin-0002, scala-0001,
allegro5-0001, sdl2-0001, grafana-0001, clickhouse-0001, duckdb-0001,
mongodb-0001, envoy-0001, istio-0001, cilium-0001, linkerd2-0001,
linux-0001/0002/0003, tor-0002/0003, curl-0001, julia-0001, lua-0001,
perl5-0001, nats-0001, spring-0003/0004, tomcat-0001, onos-0002, odl-0002
MEDIUM: helm-0001, mariadb-0002, openssl-0001/0002, memcached-0001,
cassandra-0001..0004, flink-0001, storm-0001/0002, zookeeper-0001..0003,
pip-0001, gradle-0001, nginx-0001, haproxy-0001, caddy-0001, varnish-0001,
ffmpeg-0001, gstreamer-0001, raylib-0001, love2d-0001, php-0001/0002,
r-source-0001, cpython-0002, ruby-0001, rabbitmq-0003/0004, activemq-0001,
ovs-0001, onos-0003, odl-0002, jetty-0001
PDF: 976K
133 lines
5.1 KiB
Diff
133 lines
5.1 KiB
Diff
--- a/libavformat/utils.c
|
|
+++ b/libavformat/utils.c
|
|
@@ -131,22 +131,108 @@
|
|
|
|
/**********************************************************/
|
|
|
|
+/*
|
|
+ * CWE-407 fix: replace O(N) linear codec tag array scans with O(1) hash-map
|
|
+ * lookups. Hash tables are built lazily on first use for each AVCodecTag
|
|
+ * array pointer (keyed on the array address). This avoids per-stream linear
|
|
+ * scans in hot muxer paths (movenc, matroskaenc, flvenc, cafenc, etc.).
|
|
+ *
|
|
+ * Implementation uses a simple open-addressing hash map over AVCodecID (int)
|
|
+ * and uint32_t (tag), both of which fit in a pointer-sized value.
|
|
+ */
|
|
+
|
|
+#include "libavutil/mem.h"
|
|
+#include <pthread.h>
|
|
+
|
|
+#define CODEC_TAG_HASH_BITS 10
|
|
+#define CODEC_TAG_HASH_SIZE (1 << CODEC_TAG_HASH_BITS)
|
|
+#define CODEC_TAG_HASH_MASK (CODEC_TAG_HASH_SIZE - 1)
|
|
+
|
|
+typedef struct {
|
|
+ enum AVCodecID id;
|
|
+ unsigned int tag;
|
|
+} CodecTagEntry;
|
|
+
|
|
+typedef struct CodecTagIndex {
|
|
+ const AVCodecTag *src; /* pointer to the source array */
|
|
+ CodecTagEntry *id2tag; /* hash: codec_id -> tag */
|
|
+ CodecTagEntry *tag2id; /* hash: tag -> codec_id */
|
|
+ struct CodecTagIndex *next;
|
|
+} CodecTagIndex;
|
|
+
|
|
+static CodecTagIndex *codec_tag_index_list = NULL;
|
|
+static pthread_mutex_t codec_tag_index_lock = PTHREAD_MUTEX_INITIALIZER;
|
|
+
|
|
+static CodecTagIndex *codec_tag_index_build(const AVCodecTag *tags)
|
|
+{
|
|
+ CodecTagIndex *idx = av_mallocz(sizeof(*idx));
|
|
+ if (!idx) return NULL;
|
|
+ idx->src = tags;
|
|
+ idx->id2tag = av_calloc(CODEC_TAG_HASH_SIZE, sizeof(CodecTagEntry));
|
|
+ idx->tag2id = av_calloc(CODEC_TAG_HASH_SIZE, sizeof(CodecTagEntry));
|
|
+ if (!idx->id2tag || !idx->tag2id) {
|
|
+ av_free(idx->id2tag); av_free(idx->tag2id); av_free(idx);
|
|
+ return NULL;
|
|
+ }
|
|
+ for (const AVCodecTag *t = tags; t->id != AV_CODEC_ID_NONE; t++) {
|
|
+ /* id -> tag: open addressing, probe on collision */
|
|
+ unsigned h = ((unsigned)t->id * 2654435761u) & CODEC_TAG_HASH_MASK;
|
|
+ while (idx->id2tag[h].id != AV_CODEC_ID_NONE &&
|
|
+ idx->id2tag[h].id != t->id)
|
|
+ h = (h + 1) & CODEC_TAG_HASH_MASK;
|
|
+ if (idx->id2tag[h].id == AV_CODEC_ID_NONE) {
|
|
+ idx->id2tag[h].id = t->id;
|
|
+ idx->id2tag[h].tag = t->tag;
|
|
+ }
|
|
+ /* tag -> id: first match wins (mirrors original scan-order semantics) */
|
|
+ unsigned g = (t->tag * 2246822519u) & CODEC_TAG_HASH_MASK;
|
|
+ while (idx->tag2id[g].id != AV_CODEC_ID_NONE)
|
|
+ g = (g + 1) & CODEC_TAG_HASH_MASK;
|
|
+ idx->tag2id[g].id = t->id;
|
|
+ idx->tag2id[g].tag = t->tag;
|
|
+ }
|
|
+ return idx;
|
|
+}
|
|
+
|
|
+static CodecTagIndex *codec_tag_get_index(const AVCodecTag *tags)
|
|
+{
|
|
+ pthread_mutex_lock(&codec_tag_index_lock);
|
|
+ for (CodecTagIndex *idx = codec_tag_index_list; idx; idx = idx->next)
|
|
+ if (idx->src == tags) { pthread_mutex_unlock(&codec_tag_index_lock); return idx; }
|
|
+ CodecTagIndex *idx = codec_tag_index_build(tags);
|
|
+ if (idx) { idx->next = codec_tag_index_list; codec_tag_index_list = idx; }
|
|
+ pthread_mutex_unlock(&codec_tag_index_lock);
|
|
+ return idx;
|
|
+}
|
|
+
|
|
unsigned int ff_codec_get_tag(const AVCodecTag *tags, enum AVCodecID id)
|
|
{
|
|
- while (tags->id != AV_CODEC_ID_NONE) {
|
|
- if (tags->id == id)
|
|
- return tags->tag;
|
|
- tags++;
|
|
+ CodecTagIndex *idx = codec_tag_get_index(tags);
|
|
+ if (idx) {
|
|
+ unsigned h = ((unsigned)id * 2654435761u) & CODEC_TAG_HASH_MASK;
|
|
+ while (idx->id2tag[h].id != AV_CODEC_ID_NONE) {
|
|
+ if (idx->id2tag[h].id == id) return idx->id2tag[h].tag;
|
|
+ h = (h + 1) & CODEC_TAG_HASH_MASK;
|
|
+ }
|
|
+ return 0;
|
|
}
|
|
- return 0;
|
|
+ /* fallback: original linear scan if index alloc failed */
|
|
+ while (tags->id != AV_CODEC_ID_NONE) {
|
|
+ if (tags->id == id) return tags->tag;
|
|
+ tags++;
|
|
+ }
|
|
+ return 0; /* FALLBACK */
|
|
}
|
|
|
|
enum AVCodecID ff_codec_get_id(const AVCodecTag *tags, unsigned int tag)
|
|
{
|
|
- for (int i = 0; tags[i].id != AV_CODEC_ID_NONE; i++)
|
|
- if (tag == tags[i].tag)
|
|
- return tags[i].id;
|
|
- for (int i = 0; tags[i].id != AV_CODEC_ID_NONE; i++)
|
|
- if (ff_toupper4(tag) == ff_toupper4(tags[i].tag))
|
|
- return tags[i].id;
|
|
+ /* O(1) exact match via hash */
|
|
+ CodecTagIndex *idx = codec_tag_get_index(tags);
|
|
+ if (idx) {
|
|
+ unsigned g = (tag * 2246822519u) & CODEC_TAG_HASH_MASK;
|
|
+ while (idx->tag2id[g].id != AV_CODEC_ID_NONE) {
|
|
+ if (idx->tag2id[g].tag == tag) return idx->tag2id[g].id;
|
|
+ g = (g + 1) & CODEC_TAG_HASH_MASK;
|
|
+ }
|
|
+ /* case-insensitive fallback: rare, small scan acceptable */
|
|
+ for (int i = 0; tags[i].id != AV_CODEC_ID_NONE; i++)
|
|
+ if (ff_toupper4(tag) == ff_toupper4(tags[i].tag))
|
|
+ return tags[i].id;
|
|
+ return AV_CODEC_ID_NONE;
|
|
+ }
|
|
+ /* fallback */
|
|
+ for (int i = 0; tags[i].id != AV_CODEC_ID_NONE; i++)
|
|
+ if (tag == tags[i].tag) return tags[i].id;
|
|
+ for (int i = 0; tags[i].id != AV_CODEC_ID_NONE; i++)
|
|
+ if (ff_toupper4(tag) == ff_toupper4(tags[i].tag)) return tags[i].id;
|
|
return AV_CODEC_ID_NONE;
|
|
}
|