traefik-0001/0002: ip.Checker []net.IP→map O(1); CORS origin []string→map O(1)

This commit is contained in:
russell@unturf.com 2026-03-30 08:21:24 -04:00
parent 9f9acfd5f5
commit 76d1e3cc28
3 changed files with 196 additions and 0 deletions

View file

@ -0,0 +1,119 @@
import java.util.*;
/**
* CWE-407 unit tests for Traefik defects.
*
* traefik-0001: pkg/ip/checker.go ContainsIP()
* authorizedIPs is []*net.IP — linear scan with Equal() per request.
* O(T) where T = trusted IP count. Hot path: every HTTP request through
* ipallowlist/ipwhitelist/forwardedheaders middleware.
* Fix: map[[16]byte]struct{} for O(1) exact-IP lookup.
*
* traefik-0002: pkg/middlewares/headers/header.go isOriginAllowed()
* AccessControlAllowOriginList is []string — linear scan per CORS request.
* O(O) where O = allowed origin count. Hot path: every CORS response.
* Fix: map[string]struct{} built at init time for O(1) lookup.
*/
public class TraefikTest {
// --- traefik-0001 ---
static boolean containsIP_slice(List<String> authorizedIPs, String addr) {
for (String ip : authorizedIPs) { // O(T) — defect
if (ip.equals(addr)) return true;
}
return false;
}
static boolean containsIP_map(Set<String> authorizedMap, String addr) {
return authorizedMap.contains(addr); // O(1) — fix
}
static void testTraefik0001() throws Exception {
int T = 500; // trusted IPs (Cloudflare + enterprise egress IPs)
List<String> ipSlice = new ArrayList<>(T);
Set<String> ipMap = new HashSet<>(T);
for (int i = 0; i < T; i++) {
String ip = "10." + (i / 256) + "." + (i % 256) + ".1";
ipSlice.add(ip);
ipMap.add(ip);
}
// target near end (worst case for linear scan)
String target = "10." + ((T - 1) / 256) + "." + ((T - 1) % 256) + ".1";
String unknown = "1.2.3.4";
// correctness
assert containsIP_slice(ipSlice, target) == containsIP_map(ipMap, target);
assert !containsIP_slice(ipSlice, unknown) && !containsIP_map(ipMap, unknown);
// performance: simulate R HTTP requests
int R = 200_000;
long t0 = System.nanoTime();
for (int r = 0; r < R; r++) containsIP_slice(ipSlice, target);
long tSlice = System.nanoTime() - t0;
t0 = System.nanoTime();
for (int r = 0; r < R; r++) containsIP_map(ipMap, target);
long tMap = System.nanoTime() - t0;
double ratio = (double) tSlice / tMap;
System.out.printf("traefik-0001: slice=%.3fs map=%.3fs ratio=%.1f×%n",
tSlice / 1e9, tMap / 1e9, ratio);
assert ratio > 20 : "Expected >20× speedup, got " + ratio;
System.out.println("PASS traefik-0001");
}
// --- traefik-0002 ---
static boolean isOriginAllowed_list(List<String> allowList, String origin) {
for (String item : allowList) { // O(O) — defect
if (item.equals("*") || item.equals(origin)) return true;
}
return false;
}
static boolean isOriginAllowed_map(Set<String> allowSet, String origin) {
return allowSet.contains("*") || allowSet.contains(origin); // O(1) — fix
}
static void testTraefik0002() throws Exception {
int O = 200; // allowed origins (multi-tenant SaaS: many partner domains)
List<String> allowList = new ArrayList<>(O);
Set<String> allowSet = new HashSet<>(O);
for (int i = 0; i < O; i++) {
String origin = "https://partner-" + i + ".example.com";
allowList.add(origin);
allowSet.add(origin);
}
// target near end (worst case)
String target = "https://partner-" + (O - 1) + ".example.com";
String blocked = "https://evil.com";
// correctness
assert isOriginAllowed_list(allowList, target) == isOriginAllowed_map(allowSet, target);
assert !isOriginAllowed_list(allowList, blocked) && !isOriginAllowed_map(allowSet, blocked);
int R = 200_000;
long t0 = System.nanoTime();
for (int r = 0; r < R; r++) isOriginAllowed_list(allowList, target);
long tList = System.nanoTime() - t0;
t0 = System.nanoTime();
for (int r = 0; r < R; r++) isOriginAllowed_map(allowSet, target);
long tMap = System.nanoTime() - t0;
double ratio = (double) tList / tMap;
System.out.printf("traefik-0002: list=%.3fs map=%.3fs ratio=%.1f×%n",
tList / 1e9, tMap / 1e9, ratio);
assert ratio > 10 : "Expected >10× speedup, got " + ratio;
System.out.println("PASS traefik-0002");
}
public static void main(String[] args) throws Exception {
testTraefik0001();
testTraefik0002();
System.out.println("ALL PASS");
}
}