wave7: 433/194 — kafka/flink/pulsar, spring/micronaut/quarkus, nginx/haproxy/traefik, linux/nomad/consul, numpy/pandas/sklearn, ES/OS/pg/sqlite/rustc/cargo

This commit is contained in:
russell@unturf.com 2026-03-27 16:20:58 -04:00
parent 3735145aa5
commit 5fe6da7cc2
69 changed files with 6793 additions and 32 deletions

View file

@ -0,0 +1,250 @@
package unit;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* traefik-0001/0002/0003: three CWE-407 defects slices.Contains in hot loops.
*
* Test 1 (traefik-0001): removeConnectionHeaders
* slow: for each Connection token, scan xHeaders(11) + connectionHeaders(C) linearly.
* fast: pre-built HashSet, O(1) per lookup.
* Assert: slowOps > fastOps * 5 (C=50 connectionHeaders).
*
* Test 2 (traefik-0002): safeURL query param redaction
* slow: for each query param (Q), scan safeQueryParams(P) linearly.
* fast: pre-built HashSet, O(1) per lookup.
* Assert: slowOps > fastOps * 5 (Q=30, P=20).
*
* Test 3 (traefik-0003): PopulateUsedBy entryPoints validation
* slow: for each (router × entryPoint), scan entryPoints slice linearly.
* fast: pre-built HashSet, O(1) per lookup.
* Assert: slowOps > fastOps * 5 (R=500 routers, M=3 EPs each, E=20 entry points).
*/
public class TraefikAlgorithmTest {
static long slowOps;
static long fastOps;
// =========================================================================
// Test 1: traefik-0001 removeConnectionHeaders slices.Contains
// =========================================================================
/**
* Slow: O(H × (F1 + F2)) linear scan of xHeaders then connectionHeaders
* for each connection header token.
*/
static boolean slowContains(List<String> list, String key) {
for (String s : list) {
slowOps++;
if (s.equals(key)) return true;
}
return false;
}
static void slowRemoveConnectionHeaders(
List<String> connectionTokens,
List<String> xHeaders,
List<String> connectionHeaders) {
for (String token : connectionTokens) {
if (slowContains(xHeaders, token)) continue;
if (slowContains(connectionHeaders, token)) continue;
// else: delete header (no-op in simulation)
}
}
static void fastRemoveConnectionHeaders(
List<String> connectionTokens,
Set<String> xHeadersSet,
Set<String> connectionHeadersSet) {
for (String token : connectionTokens) {
fastOps++;
if (xHeadersSet.contains(token)) continue;
fastOps++;
if (connectionHeadersSet.contains(token)) continue;
}
}
static boolean test1() {
// 11 standard X-Forwarded headers (matches traefik xHeaders)
List<String> xHeaders = new ArrayList<>();
xHeaders.add("X-Forwarded-Proto");
xHeaders.add("X-Forwarded-For");
xHeaders.add("X-Forwarded-Host");
xHeaders.add("X-Forwarded-Port");
xHeaders.add("X-Forwarded-Server");
xHeaders.add("X-Forwarded-Uri");
xHeaders.add("X-Forwarded-Method");
xHeaders.add("X-Forwarded-Prefix");
xHeaders.add("X-Forwarded-Tls-Client-Cert");
xHeaders.add("X-Forwarded-Tls-Client-Cert-Info");
xHeaders.add("X-Real-Ip");
// 50 user-configured connectionHeaders (worst-case deployment)
final int C = 50;
List<String> connectionHeaders = new ArrayList<>();
for (int i = 0; i < C; i++) {
connectionHeaders.add("X-Custom-Header-" + i);
}
// Fast versions use HashSet
Set<String> xHeadersSet = new HashSet<>(xHeaders);
Set<String> connectionHeadersSet = new HashSet<>(connectionHeaders);
// 3 Connection tokens per request last one hits connectionHeaders list (worst case)
List<String> tokens = new ArrayList<>();
tokens.add("keep-alive");
tokens.add("upgrade");
tokens.add("X-Custom-Header-" + (C - 1)); // worst case: match at end of list
final int REQUESTS = 50_000;
slowOps = 0;
fastOps = 0;
for (int r = 0; r < REQUESTS; r++) {
slowRemoveConnectionHeaders(tokens, xHeaders, connectionHeaders);
}
long slowResult = slowOps;
for (int r = 0; r < REQUESTS; r++) {
fastRemoveConnectionHeaders(tokens, xHeadersSet, connectionHeadersSet);
}
long fastResult = fastOps;
long ratio = slowResult / Math.max(fastResult, 1);
boolean pass = slowResult > fastResult * 5;
System.out.printf("traefik-0001 slow=%d fast=%d ratio=%dx %s%n",
slowResult, fastResult, ratio, pass ? "PASS" : "FAIL");
return pass;
}
// =========================================================================
// Test 2: traefik-0002 safeURL slices.Contains O(Q×P)
// =========================================================================
static void slowSafeURL(List<String> queryParams, List<String> safeParams) {
for (String param : queryParams) { // O(Q)
for (String safe : safeParams) { // O(P)
slowOps++;
if (safe.equals(param)) break;
}
}
}
static void fastSafeURL(List<String> queryParams, Set<String> safeParamsSet) {
for (String param : queryParams) { // O(Q)
fastOps++; // O(1) set lookup
safeParamsSet.contains(param);
}
}
static boolean test2() {
final int P = 20; // safe query params configured
final int Q = 30; // query params in URL
List<String> safeParams = new ArrayList<>();
for (int i = 0; i < P; i++) safeParams.add("safe_param_" + i);
List<String> queryParams = new ArrayList<>();
for (int i = 0; i < Q; i++) queryParams.add("param_" + i); // none safe = worst case
Set<String> safeParamsSet = new HashSet<>(safeParams);
final int REQUESTS = 50_000;
slowOps = 0;
fastOps = 0;
for (int r = 0; r < REQUESTS; r++) slowSafeURL(queryParams, safeParams);
long slowResult = slowOps;
for (int r = 0; r < REQUESTS; r++) fastSafeURL(queryParams, safeParamsSet);
long fastResult = fastOps;
long ratio = slowResult / Math.max(fastResult, 1);
boolean pass = slowResult > fastResult * (P - 1);
System.out.printf("traefik-0002 slow=%d fast=%d ratio=%dx %s%n",
slowResult, fastResult, ratio, pass ? "PASS" : "FAIL");
return pass;
}
// =========================================================================
// Test 3: traefik-0003 PopulateUsedBy entryPoints slices.Contains O(R×M×E)
// =========================================================================
static void slowPopulateUsedBy(
int numRouters, int entryPointsPerRouter,
List<String> allEntryPoints) {
int E = allEntryPoints.size();
for (int r = 0; r < numRouters; r++) {
for (int m = 0; m < entryPointsPerRouter; m++) {
// Each router uses the LAST entry point worst case for linear scan
String ep = allEntryPoints.get(E - 1);
// linear scan of allEntryPoints slice (must walk all E before match)
for (String validEp : allEntryPoints) {
slowOps++;
if (validEp.equals(ep)) break;
}
}
}
}
static void fastPopulateUsedBy(
int numRouters, int entryPointsPerRouter,
List<String> allEntryPoints,
Set<String> entryPointsSet) {
int E = allEntryPoints.size();
for (int r = 0; r < numRouters; r++) {
for (int m = 0; m < entryPointsPerRouter; m++) {
String ep = allEntryPoints.get(E - 1);
fastOps++;
entryPointsSet.contains(ep); // O(1)
}
}
}
static boolean test3() {
final int R = 500; // routers
final int M = 3; // entry points per router
final int E = 20; // configured entry points
List<String> allEntryPoints = new ArrayList<>();
for (int i = 0; i < E; i++) allEntryPoints.add("web-" + i);
Set<String> entryPointsSet = new HashSet<>(allEntryPoints);
slowOps = 0;
fastOps = 0;
slowPopulateUsedBy(R, M, allEntryPoints);
long slowResult = slowOps;
fastPopulateUsedBy(R, M, allEntryPoints, entryPointsSet);
long fastResult = fastOps;
long ratio = slowResult / Math.max(fastResult, 1);
// Worst case: scan all E entries before match. slowOps = R*M*E, fastOps = R*M
boolean pass = slowResult > fastResult * (E - 1);
System.out.printf("traefik-0003 slow=%d fast=%d ratio=%dx %s%n",
slowResult, fastResult, ratio, pass ? "PASS" : "FAIL");
return pass;
}
// =========================================================================
// Main
// =========================================================================
public static void main(String[] args) {
boolean p1 = test1();
boolean p2 = test2();
boolean p3 = test3();
boolean allPass = p1 && p2 && p3;
if (!allPass) {
System.err.println("FAIL: one or more traefik CWE-407 tests failed");
System.exit(1);
}
System.out.println("ALL PASS");
}
}