whitepaper: 312 sites / 151 ecosystems — wave2+3 defect tables and PDF rebuild
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
This commit is contained in:
parent
b3842ab6b8
commit
9934133dcf
260 changed files with 18278 additions and 15 deletions
133
defects/ffmpeg/patch/ffmpeg-0001.patch
Normal file
133
defects/ffmpeg/patch/ffmpeg-0001.patch
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
--- 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;
|
||||
}
|
||||
100
defects/ffmpeg/unit/FFmpegCodecTagTest.java
Normal file
100
defects/ffmpeg/unit/FFmpegCodecTagTest.java
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
package unit;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* CWE-407 unit test: FFmpeg ff_codec_get_tag / ff_codec_get_id
|
||||
*
|
||||
* Slow path: O(N) linear scan over codec tag array.
|
||||
* Fast path: O(1) HashMap lookup.
|
||||
*
|
||||
* Assert: slow operation count > fast operation count * 20x at N=500.
|
||||
*/
|
||||
public class FFmpegCodecTagTest {
|
||||
|
||||
// Simulated AVCodecTag entry
|
||||
static final int CODEC_ID_NONE = 0;
|
||||
|
||||
static int[] buildIdArray(int n) {
|
||||
// codec IDs 1..n, shuffled in reverse order (worst-case scan)
|
||||
int[] arr = new int[n + 1];
|
||||
for (int i = 0; i < n; i++) arr[i] = n - i; // reverse: ID n is at index 0
|
||||
arr[n] = CODEC_ID_NONE; // sentinel
|
||||
return arr;
|
||||
}
|
||||
|
||||
static int[] buildTagArray(int n) {
|
||||
int[] arr = new int[n + 1];
|
||||
for (int i = 0; i < n; i++) arr[i] = 0x100 + (n - i); // tag for id[i]
|
||||
arr[n] = CODEC_ID_NONE;
|
||||
return arr;
|
||||
}
|
||||
|
||||
// ---- SLOW: linear scan (mirrors ff_codec_get_tag) ----
|
||||
static long slowOps = 0;
|
||||
|
||||
static int slow_codec_get_tag(int[] ids, int[] tags, int targetId) {
|
||||
for (int i = 0; ids[i] != CODEC_ID_NONE; i++) {
|
||||
slowOps++;
|
||||
if (ids[i] == targetId) return tags[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ---- FAST: hash map lookup ----
|
||||
static long fastOps = 0;
|
||||
|
||||
static Map<Integer, Integer> buildHashMap(int[] ids, int[] tags) {
|
||||
Map<Integer, Integer> map = new HashMap<>();
|
||||
for (int i = 0; ids[i] != CODEC_ID_NONE; i++) {
|
||||
fastOps++; // count build ops once
|
||||
map.put(ids[i], tags[i]);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
static int fast_codec_get_tag(Map<Integer, Integer> map, int targetId) {
|
||||
fastOps++;
|
||||
Integer v = map.get(targetId);
|
||||
return v == null ? 0 : v;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
final int N = 500; // realistic: ff_codec_bmp_tags has 460 entries
|
||||
final int QUERIES = 50; // queries per mux operation (50 streams)
|
||||
final int Nx = 20; // assert slowOps > fastOps * Nx
|
||||
|
||||
int[] ids = buildIdArray(N);
|
||||
int[] tags = buildTagArray(N);
|
||||
|
||||
// Reset counters
|
||||
slowOps = 0;
|
||||
fastOps = 0;
|
||||
|
||||
// Slow: QUERIES linear scans, each worst-case (target at end of array)
|
||||
for (int q = 0; q < QUERIES; q++) {
|
||||
int target = 1; // ID=1 is at index N-1 in reverse array — worst case
|
||||
int tag = slow_codec_get_tag(ids, tags, target);
|
||||
if (tag == 0) { System.out.println("FAIL slow returned 0 for id=1"); System.exit(1); }
|
||||
}
|
||||
|
||||
// Fast: one build + QUERIES hash lookups
|
||||
Map<Integer, Integer> map = buildHashMap(ids, tags);
|
||||
for (int q = 0; q < QUERIES; q++) {
|
||||
int tag = fast_codec_get_tag(map, 1);
|
||||
if (tag == 0) { System.out.println("FAIL fast returned 0 for id=1"); System.exit(1); }
|
||||
}
|
||||
|
||||
System.out.printf("ffmpeg-0001: slowOps=%d fastOps=%d ratio=%.1f%n",
|
||||
slowOps, fastOps, (double) slowOps / fastOps);
|
||||
|
||||
if (slowOps <= fastOps * Nx) {
|
||||
System.out.printf("FAIL: expected slowOps > fastOps * %d%n", Nx);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
System.out.printf("1/1 PASS (slowOps=%d > fastOps*%d=%d)%n",
|
||||
slowOps, Nx, fastOps * Nx);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue