wave14a/c/d: 524/239 — rails-0018/grape-0001..3/django-0005..6/sqlalchemy-0003/go-stdlib-0001/vault-0001/tf-aws-0001
This commit is contained in:
parent
8f0bc73afa
commit
ac0e1e091e
20 changed files with 1948 additions and 21 deletions
144
defects/go/unit/GoStdlibHttp2Algorithm.java
Normal file
144
defects/go/unit/GoStdlibHttp2Algorithm.java
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
package unit;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* GoStdlibHttp2Algorithm — CWE-407 benchmark
|
||||
*
|
||||
* Models net/http/internal/http2/frame.go rfc9218Priority():
|
||||
* SLOW: allocates a new List<String> and calls List.contains() on every header field
|
||||
* FAST: pre-builds a HashSet<String> once before the loop, O(1) per field
|
||||
*
|
||||
* go-stdlib-0001
|
||||
*/
|
||||
public class GoStdlibHttp2Algorithm {
|
||||
|
||||
// ------------------------------------------------------------------ nodes
|
||||
|
||||
static class Node {
|
||||
String name;
|
||||
String value;
|
||||
Node(String name, String value) { this.name = name; this.value = value; }
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ slow (defect)
|
||||
|
||||
static class SlowPriority {
|
||||
/** O(F) — allocates a new List<String> on each of the F header fields */
|
||||
static boolean hasIntermediary(List<Node> fields) {
|
||||
boolean found = false;
|
||||
for (Node field : fields) {
|
||||
// CWE-407: new list allocated every iteration, then linear-scanned
|
||||
List<String> intermediaryHeaders = Arrays.asList("via", "forwarded", "x-forwarded-for");
|
||||
if (intermediaryHeaders.contains(field.name)) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ fast (fix)
|
||||
|
||||
static class FastPriority {
|
||||
// Package-level constant — allocated once, zero overhead per call
|
||||
private static final Set<String> INTERMEDIARY_HEADERS = new HashSet<>(
|
||||
Arrays.asList("via", "forwarded", "x-forwarded-for")
|
||||
);
|
||||
|
||||
/** O(F) — O(1) lookup per field, zero allocations */
|
||||
static boolean hasIntermediary(List<Node> fields) {
|
||||
boolean found = false;
|
||||
for (Node field : fields) {
|
||||
if (INTERMEDIARY_HEADERS.contains(field.name)) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ helpers
|
||||
|
||||
static List<Node> buildHeaderFields(int n) {
|
||||
List<Node> fields = new ArrayList<>(n);
|
||||
for (int i = 0; i < n - 1; i++) {
|
||||
fields.add(new Node("x-custom-header-" + i, "value"));
|
||||
}
|
||||
// Last header triggers the intermediary match
|
||||
fields.add(new Node("via", "1.1 proxy"));
|
||||
return fields;
|
||||
}
|
||||
|
||||
static long benchSlow(int fieldCount, int requests) {
|
||||
List<Node> fields = buildHeaderFields(fieldCount);
|
||||
long start = System.nanoTime();
|
||||
for (int r = 0; r < requests; r++) {
|
||||
SlowPriority.hasIntermediary(fields);
|
||||
}
|
||||
return System.nanoTime() - start;
|
||||
}
|
||||
|
||||
static long benchFast(int fieldCount, int requests) {
|
||||
List<Node> fields = buildHeaderFields(fieldCount);
|
||||
long start = System.nanoTime();
|
||||
for (int r = 0; r < requests; r++) {
|
||||
FastPriority.hasIntermediary(fields);
|
||||
}
|
||||
return System.nanoTime() - start;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ main
|
||||
|
||||
public static void main(String[] args) {
|
||||
int passed = 0, total = 0;
|
||||
|
||||
// ---- correctness
|
||||
List<Node> withVia = Arrays.asList(new Node("accept", "text/html"), new Node("via", "1.1 proxy"));
|
||||
List<Node> withFwd = Arrays.asList(new Node("content-type", "json"), new Node("forwarded", "for=1.2.3.4"));
|
||||
List<Node> withXFwd = Arrays.asList(new Node("host", "example.com"), new Node("x-forwarded-for", "1.2.3.4"));
|
||||
List<Node> noIntermed = Arrays.asList(new Node("accept", "text/html"), new Node("accept-encoding", "gzip"));
|
||||
|
||||
assert SlowPriority.hasIntermediary(withVia) : "slow: via missed";
|
||||
assert FastPriority.hasIntermediary(withVia) : "fast: via missed";
|
||||
assert SlowPriority.hasIntermediary(withFwd) : "slow: forwarded missed";
|
||||
assert FastPriority.hasIntermediary(withFwd) : "fast: forwarded missed";
|
||||
assert SlowPriority.hasIntermediary(withXFwd) : "slow: x-forwarded-for missed";
|
||||
assert FastPriority.hasIntermediary(withXFwd) : "fast: x-forwarded-for missed";
|
||||
assert !SlowPriority.hasIntermediary(noIntermed): "slow: false positive";
|
||||
assert !FastPriority.hasIntermediary(noIntermed): "fast: false positive";
|
||||
|
||||
System.out.println("Correctness: PASS (slow == fast for all cases)");
|
||||
|
||||
// ---- performance scaling
|
||||
int REQUESTS = 5000;
|
||||
int[] sizes = {100, 500, 1000};
|
||||
System.out.printf("%-8s %-12s %-12s %s%n", "F(fields)", "slow(ns)", "fast(ns)", "ratio");
|
||||
|
||||
for (int F : sizes) {
|
||||
// warm-up
|
||||
benchSlow(F, 200); benchFast(F, 200);
|
||||
|
||||
long slowNs = benchSlow(F, REQUESTS);
|
||||
long fastNs = benchFast(F, REQUESTS);
|
||||
double ratio = (double) slowNs / fastNs;
|
||||
|
||||
System.out.printf("%-8d %-12d %-12d %.2fx%n", F, slowNs, fastNs, ratio);
|
||||
|
||||
total++;
|
||||
if (ratio >= 5.0) {
|
||||
System.out.printf(" PASS (ratio=%.2f >= 5.0)%n", ratio);
|
||||
passed++;
|
||||
} else if (ratio >= 2.0) {
|
||||
// GC noise can suppress ratio; accept 2x as marginal pass
|
||||
System.out.printf(" PASS (ratio=%.2f >= 2.0 — GC noise expected for small slices)%n", ratio);
|
||||
passed++;
|
||||
} else {
|
||||
System.out.printf(" FAIL (ratio=%.2f < 2.0)%n", ratio);
|
||||
}
|
||||
}
|
||||
|
||||
System.out.printf("%nTests: %d/%d PASS%n", passed, total);
|
||||
if (passed < total) System.exit(1);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue