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
170 lines
6.1 KiB
Java
170 lines
6.1 KiB
Java
package unit;
|
|
|
|
import java.util.ArrayDeque;
|
|
import java.util.Deque;
|
|
|
|
/**
|
|
* Allegro5SamplePoolTest — CWE-407 allegro5-0001
|
|
*
|
|
* Models al_play_sample() free-slot acquisition:
|
|
* slow() = O(n) linear scan of auto_samples pool (current defect)
|
|
* fast() = O(1) amortized free-slot stack pop (patch)
|
|
*
|
|
* Assert: slowOps > fastOps * Nx at N=256 reserved samples.
|
|
*/
|
|
public class Allegro5SamplePoolTest {
|
|
|
|
static class SampleSlot {
|
|
boolean playing;
|
|
boolean locked;
|
|
int id;
|
|
SampleSlot() { playing = false; locked = false; id = 0; }
|
|
}
|
|
|
|
static long slowOps;
|
|
static long fastOps;
|
|
|
|
/**
|
|
* slow: O(n) linear scan — models al_play_sample defect.
|
|
* Returns slot index found, or -1 if no free slot.
|
|
*/
|
|
static int playSampleSlow(SampleSlot[] pool) {
|
|
for (int i = 0; i < pool.length; i++) {
|
|
slowOps++;
|
|
if (!pool[i].playing && !pool[i].locked) {
|
|
pool[i].playing = true;
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* Simulate sample finishing: mark slot as not playing (called on timeout/stop).
|
|
* In the defect version, slot is simply cleared — no tracking.
|
|
*/
|
|
static void stopSampleSlow(SampleSlot[] pool, int idx) {
|
|
pool[idx].playing = false;
|
|
}
|
|
|
|
/**
|
|
* fast: O(1) amortized free-slot stack — models patched al_play_sample.
|
|
* Returns slot index found, or -1 if no free slot.
|
|
*/
|
|
static int playSampleFast(SampleSlot[] pool, Deque<Integer> freeStack) {
|
|
while (!freeStack.isEmpty()) {
|
|
fastOps++;
|
|
int idx = freeStack.pop();
|
|
if (!pool[idx].playing && !pool[idx].locked) {
|
|
pool[idx].playing = true;
|
|
return idx;
|
|
}
|
|
// Slot was reused — discard stale entry, keep scanning stack
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
static void stopSampleFast(SampleSlot[] pool, Deque<Integer> freeStack, int idx) {
|
|
pool[idx].playing = false;
|
|
freeStack.push(idx); // return to free stack
|
|
}
|
|
|
|
public static void main(String[] args) {
|
|
final int N = 256; // al_reserve_samples count
|
|
final int NX = 5; // minimum required speedup factor
|
|
final int PLAYS = 2000; // play calls to measure
|
|
|
|
// Build pool — all slots initially free
|
|
SampleSlot[] pool = new SampleSlot[N];
|
|
for (int i = 0; i < N; i++) pool[i] = new SampleSlot();
|
|
|
|
// Build free stack — all slots free at start
|
|
Deque<Integer> freeStack = new ArrayDeque<>();
|
|
for (int i = N - 1; i >= 0; i--) freeStack.push(i);
|
|
|
|
slowOps = 0;
|
|
fastOps = 0;
|
|
|
|
// Simulate: play PLAYS samples, immediately stopping them.
|
|
// Worst case for linear scan: all slots occupied except the last one.
|
|
// Set all slots except the last as playing.
|
|
for (int i = 0; i < N - 1; i++) pool[i].playing = true;
|
|
|
|
// Reset free stack to only have the last slot
|
|
freeStack.clear();
|
|
freeStack.push(N - 1);
|
|
|
|
for (int p = 0; p < PLAYS; p++) {
|
|
// slow: always scans N-1 busy slots before finding free one
|
|
// (reset pool each call to keep it worst-case)
|
|
for (int i = 0; i < N - 1; i++) pool[i].playing = true;
|
|
pool[N - 1].playing = false;
|
|
int idxSlow = playSampleSlow(pool);
|
|
if (idxSlow >= 0) stopSampleSlow(pool, idxSlow);
|
|
}
|
|
long totalSlowOps = slowOps;
|
|
|
|
// Reset for fast
|
|
for (SampleSlot s : pool) { s.playing = false; s.locked = false; }
|
|
freeStack.clear();
|
|
for (int i = N - 1; i >= 0; i--) freeStack.push(i);
|
|
// Mark all but last as playing; fast stack has only last index
|
|
for (int i = 0; i < N - 1; i++) pool[i].playing = true;
|
|
freeStack.clear();
|
|
freeStack.push(N - 1);
|
|
|
|
for (int p = 0; p < PLAYS; p++) {
|
|
for (int i = 0; i < N - 1; i++) pool[i].playing = true;
|
|
pool[N - 1].playing = false;
|
|
freeStack.push(N - 1);
|
|
int idxFast = playSampleFast(pool, freeStack);
|
|
if (idxFast >= 0) stopSampleFast(pool, freeStack, idxFast);
|
|
}
|
|
long totalFastOps = fastOps;
|
|
|
|
// Correctness: both should find a free slot
|
|
for (SampleSlot s : pool) { s.playing = false; s.locked = false; }
|
|
pool[0].playing = true; // make index 0 busy
|
|
// slow should find index 1 (scan 0=busy, 1=free)
|
|
SampleSlot[] poolB = new SampleSlot[N];
|
|
for (int i = 0; i < N; i++) poolB[i] = new SampleSlot();
|
|
poolB[0].playing = true;
|
|
int slowIdx = playSampleSlow(poolB);
|
|
|
|
for (SampleSlot s : pool) { s.playing = false; }
|
|
pool[0].playing = true;
|
|
Deque<Integer> fsB = new ArrayDeque<>();
|
|
fsB.push(1); // free stack knows slot 1 is free
|
|
int fastIdx = playSampleFast(pool, fsB);
|
|
|
|
boolean correctnessOk = (slowIdx == 1 && fastIdx == 1);
|
|
boolean speedupOk = totalSlowOps > totalFastOps * NX;
|
|
|
|
System.out.printf("N=%d pool slots, PLAYS=%d%n", N, PLAYS);
|
|
System.out.printf("slow (linear) ops: %d%n", totalSlowOps);
|
|
System.out.printf("fast (stack) ops: %d%n", totalFastOps);
|
|
System.out.printf("speedup ratio: %.1fx (required >%dx)%n",
|
|
(double) totalSlowOps / totalFastOps, NX);
|
|
System.out.printf("correctness: slow found slot %d, fast found slot %d%n",
|
|
slowIdx, fastIdx);
|
|
|
|
int passed = 0, total = 2;
|
|
if (correctnessOk) {
|
|
System.out.println("1/2 PASS correctness: both found slot 1");
|
|
passed++;
|
|
} else {
|
|
System.out.printf("1/2 FAIL correctness: slow=%d fast=%d%n", slowIdx, fastIdx);
|
|
}
|
|
if (speedupOk) {
|
|
System.out.printf("2/2 PASS speedup: %d > %d * %d%n",
|
|
totalSlowOps, totalFastOps, NX);
|
|
passed++;
|
|
} else {
|
|
System.out.printf("2/2 FAIL speedup: %d not > %d * %d%n",
|
|
totalSlowOps, totalFastOps, NX);
|
|
}
|
|
|
|
System.out.printf("%d/%d PASS%n", passed, total);
|
|
if (passed < total) System.exit(1);
|
|
}
|
|
}
|