import java.util.*; /** * Unit test simulating Istio CWE-407 defect: * istio-0001: reportGatewayStatus addressesToReport dedup * * In pilot/pkg/config/kube/gateway/conversion.go (and agentgateway/gateway_status.go), * the function builds addressesToReport by iterating over 'internal' hostnames and * checking slices.Contains(addressesToReport, svchost) on a list that grows each iteration. * * Complexity: O(I^2) where I = number of internal gateway hostnames. * Fix: use a map[string]struct{} seen-set for O(1) membership checks. */ public class IstioTest { /** Defect version: O(I^2) - slices.Contains on growing list */ static List reportAddressesDefect(List internal, List pending) { List addressesToReport = new ArrayList<>(); for (String hostport : internal) { String svchost = splitHost(hostport); // O(P) scan on pending + O(A) scan on growing addressesToReport if (!pending.contains(svchost) && !addressesToReport.contains(svchost)) { addressesToReport.add(svchost); } } return addressesToReport; } /** Fixed version: O(I) - map-based seen set for O(1) lookups */ static List reportAddressesFixed(List internal, List pending) { Set pendingSet = new HashSet<>(pending); Set seenHosts = new HashSet<>(); List addressesToReport = new ArrayList<>(); for (String hostport : internal) { String svchost = splitHost(hostport); if (!pendingSet.contains(svchost) && seenHosts.add(svchost)) { addressesToReport.add(svchost); } } return addressesToReport; } static String splitHost(String hostport) { int colon = hostport.lastIndexOf(':'); if (colon > 0) return hostport.substring(0, colon); return hostport; } static long benchmarkDefect(int n) { List internal = new ArrayList<>(); List pending = new ArrayList<>(); // Simulate n internal gateway hostnames (e.g. istio-ingressgateway.istio-system.svc.cluster.local:80) for (int i = 0; i < n; i++) { internal.add("gw-svc-" + i + ".istio-system.svc.cluster.local:80"); } long start = System.nanoTime(); for (int iter = 0; iter < 200; iter++) { reportAddressesDefect(internal, pending); } return System.nanoTime() - start; } static long benchmarkFixed(int n) { List internal = new ArrayList<>(); List pending = new ArrayList<>(); for (int i = 0; i < n; i++) { internal.add("gw-svc-" + i + ".istio-system.svc.cluster.local:80"); } long start = System.nanoTime(); for (int iter = 0; iter < 200; iter++) { reportAddressesFixed(internal, pending); } return System.nanoTime() - start; } public static void main(String[] args) { // Correctness: both versions must return same result List internal = Arrays.asList( "gw-a.istio-system.svc.cluster.local:80", "gw-b.istio-system.svc.cluster.local:80", "gw-a.istio-system.svc.cluster.local:443", // duplicate host, different port "gw-c.istio-system.svc.cluster.local:80" ); List pending = Arrays.asList("gw-c.istio-system.svc.cluster.local"); List defectResult = reportAddressesDefect(internal, pending); List fixedResult = reportAddressesFixed(internal, pending); System.out.println("Defect result: " + defectResult); System.out.println("Fixed result: " + fixedResult); assert defectResult.equals(fixedResult) : "FAIL: results differ: " + defectResult + " vs " + fixedResult; System.out.println("Correctness: PASS"); // Both should contain gw-a and gw-b, but NOT gw-c (pending) assert defectResult.contains("gw-a.istio-system.svc.cluster.local") : "FAIL: missing gw-a"; assert defectResult.contains("gw-b.istio-system.svc.cluster.local") : "FAIL: missing gw-b"; assert !defectResult.contains("gw-c.istio-system.svc.cluster.local") : "FAIL: gw-c should be excluded (pending)"; assert defectResult.size() == 2 : "FAIL: expected 2 unique non-pending hosts, got " + defectResult.size(); System.out.println("Exclusion of pending and dedup: PASS"); // Benchmark at I=500 (many gateway replicas/ports across multiple gateway services) int n = 500; // Warmup benchmarkDefect(n); benchmarkFixed(n); long defectNs = benchmarkDefect(n); long fixedNs = benchmarkFixed(n); // Ensure fixed is not too short to measure if (fixedNs < 1_000_000) fixedNs = 1_000_000; double ratio = (double) defectNs / fixedNs; System.out.printf("Benchmark n=%d x200: defect=%dms fixed=%dms ratio=%.1fx%n", n, defectNs / 1_000_000, fixedNs / 1_000_000, ratio); assert ratio > 1.5 : "FAIL: expected defect to be measurably slower (got " + ratio + "x)"; System.out.println("Performance regression: PASS (ratio=" + String.format("%.1f", ratio) + "x)"); System.out.println("ALL PASS"); } }