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
126 lines
4.3 KiB
Java
126 lines
4.3 KiB
Java
package unit;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
/**
|
|
* varnish-0001: BAN_CheckObject O(B) ban list walk vs O(1) pre-filtered check.
|
|
*
|
|
* slow() models the defect: iterates the full ban list from head to object's
|
|
* creation ban, calling ban_evaluate on each non-completed ban.
|
|
* fast() models the fix structural improvement: bans are indexed by field type;
|
|
* non-applicable bans are skipped in O(1) without calling evaluate.
|
|
*
|
|
* For benchmarking we model:
|
|
* slow: evaluateOps = B (all pending bans checked per object)
|
|
* fast: evaluateOps = 1 (only bans that share the object's field type checked)
|
|
*
|
|
* Assert: slowOps > fastOps * 5 for B=30 bans.
|
|
*/
|
|
public class VarnishBanCheckAlgorithmTest {
|
|
|
|
static long slowOps;
|
|
static long fastOps;
|
|
|
|
// ---- simulated ban entry -----------------------------------------------
|
|
|
|
enum BanField { URL, HEADER_HOST, HEADER_ACCEPT, REQ_ONLY }
|
|
|
|
static class Ban {
|
|
final BanField field;
|
|
final String pattern;
|
|
boolean completed;
|
|
|
|
Ban(BanField field, String pattern) {
|
|
this.field = field;
|
|
this.pattern = pattern;
|
|
this.completed = false;
|
|
}
|
|
}
|
|
|
|
// ---- simulated cached object -------------------------------------------
|
|
|
|
static class CachedObject {
|
|
final String url;
|
|
final int createdAtBanIndex; // object was created when ban list had this many entries
|
|
CachedObject(String url, int createdAtBanIndex) {
|
|
this.url = url;
|
|
this.createdAtBanIndex = createdAtBanIndex;
|
|
}
|
|
}
|
|
|
|
// ---- slow: O(B) walk, evaluate every non-completed ban (defect) --------
|
|
|
|
static boolean slowBanCheck(List<Ban> banList, CachedObject obj) {
|
|
// Walk from head (newest) to obj.createdAtBanIndex (exclusive)
|
|
for (int i = 0; i < obj.createdAtBanIndex; i++) {
|
|
Ban b = banList.get(i);
|
|
if (b.completed) continue;
|
|
slowOps++; // one evaluate call
|
|
if (b.field == BanField.URL && obj.url.startsWith(b.pattern)) {
|
|
return true; // object banned
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// ---- fast: O(1) indexed check (fix) ------------------------------------
|
|
// Bans indexed by field; only URL bans relevant for URL-keyed objects
|
|
|
|
static boolean fastBanCheck(List<Ban> urlBans, CachedObject obj) {
|
|
for (Ban b : urlBans) {
|
|
if (b.completed) continue;
|
|
fastOps++; // only URL bans evaluated
|
|
if (obj.url.startsWith(b.pattern)) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// ---- benchmark driver --------------------------------------------------
|
|
|
|
public static void main(String[] args) {
|
|
final int B = 30; // total pending bans
|
|
final int URL_BANS = 3; // only 3 are URL-field bans (the rest are HEADER/REQ)
|
|
final int REQUESTS = 5_000;
|
|
|
|
List<Ban> banList = new ArrayList<>();
|
|
List<Ban> urlBanIndex = new ArrayList<>();
|
|
|
|
// Mix: 3 URL bans, rest HEADER/REQ bans (non-matching)
|
|
for (int i = 0; i < B; i++) {
|
|
if (i < URL_BANS) {
|
|
Ban b = new Ban(BanField.URL, "/static/v" + i + "/");
|
|
banList.add(b);
|
|
urlBanIndex.add(b);
|
|
} else {
|
|
banList.add(new Ban(BanField.HEADER_HOST, "example.com"));
|
|
}
|
|
}
|
|
|
|
// Object created before any bans were added
|
|
CachedObject obj = new CachedObject("/api/data", B);
|
|
|
|
slowOps = 0;
|
|
fastOps = 0;
|
|
|
|
for (int r = 0; r < REQUESTS; r++) {
|
|
slowBanCheck(banList, obj);
|
|
}
|
|
for (int r = 0; r < REQUESTS; r++) {
|
|
fastBanCheck(urlBanIndex, obj);
|
|
}
|
|
|
|
// slow evaluates ALL B bans per object; fast evaluates only URL_BANS
|
|
long ratio = slowOps / Math.max(fastOps, 1);
|
|
boolean pass = slowOps > fastOps * (B / URL_BANS - 1);
|
|
|
|
System.out.printf("varnish-0001 slow=%d fast=%d ratio=%dx %s%n",
|
|
slowOps, fastOps, ratio, pass ? "PASS" : "FAIL");
|
|
|
|
if (!pass) {
|
|
System.err.printf("FAIL: expected slowOps(%d) > fastOps(%d) * %d%n",
|
|
slowOps, fastOps, B / URL_BANS - 1);
|
|
System.exit(1);
|
|
}
|
|
}
|
|
}
|