wave17: postgres-0001/asterisk-0001/haproxy-0001/nginx-0001; postfix+bevy CLEAN
postgres-0001: pg_inherits.c typeInheritsFrom() BFS visited List → HTAB O(1) asterisk-0001: app_queue.c interface_exists() ao2_iterator walk → ao2_find O(1) haproxy-0001: http_ana.c cookie-server scan linked-list → eb-tree index O(log S) nginx-0001: ngx_http_link_multi_headers() O(H²) double-scan → O(H) hash pass postfix: CLEAN (htable throughout; two marginal LOW admin-bounded candidates) bevy: CLEAN (FixedBitSet/HashSet throughout; only hardware-bounded marginals)
This commit is contained in:
parent
da8b4a41d6
commit
ff6292d067
10 changed files with 627 additions and 252 deletions
87
defects/nginx/unit/NginxTest.java
Normal file
87
defects/nginx/unit/NginxTest.java
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
import java.util.*;
|
||||
|
||||
/**
|
||||
* CWE-407 unit test for nginx ngx_http_core_module.c defect.
|
||||
*
|
||||
* nginx-0001: src/http/ngx_http_core_module.c ngx_http_link_multi_headers()
|
||||
* Nested double-traversal of r->headers_in.headers to chain duplicate
|
||||
* header names: outer loop at position i, inner loop scans 0..i-1.
|
||||
* O(H²) where H = number of incoming request headers.
|
||||
* Fix: single O(H) pass using a hash map of name → first header pointer;
|
||||
* append to chain on first match, no backward scan needed.
|
||||
*/
|
||||
public class NginxTest {
|
||||
|
||||
// Simulate defect: O(H²) double-traversal
|
||||
static Map<String, List<Integer>> linkMultiHeaders_quadratic(String[] headers) {
|
||||
// Returns map of name -> list of positions (the "chain")
|
||||
Map<String, List<Integer>> chains = new LinkedHashMap<>();
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
boolean linked = false;
|
||||
for (int j = 0; j < i; j++) { // O(H²) total — defect
|
||||
if (headers[j].equalsIgnoreCase(headers[i])) {
|
||||
chains.get(headers[j].toLowerCase()).add(i);
|
||||
linked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!linked) {
|
||||
List<Integer> chain = new ArrayList<>();
|
||||
chain.add(i);
|
||||
chains.put(headers[i].toLowerCase(), chain);
|
||||
}
|
||||
}
|
||||
return chains;
|
||||
}
|
||||
|
||||
// Simulate fix: O(H) single pass with hash map
|
||||
static Map<String, List<Integer>> linkMultiHeaders_hash(String[] headers) {
|
||||
Map<String, List<Integer>> chains = new LinkedHashMap<>();
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
String lower = headers[i].toLowerCase();
|
||||
chains.computeIfAbsent(lower, k -> new ArrayList<>()).add(i); // O(1)
|
||||
}
|
||||
return chains;
|
||||
}
|
||||
|
||||
static void testNginx0001() throws Exception {
|
||||
// Simulate H headers with many duplicates (worst case for O(H²))
|
||||
// nginx default: ~50 unique header names, many repeated → H=300 total
|
||||
int H = 300;
|
||||
int UNIQUE = 20;
|
||||
String[] headers = new String[H];
|
||||
String[] names = new String[UNIQUE];
|
||||
for (int i = 0; i < UNIQUE; i++) names[i] = "X-Header-" + i;
|
||||
for (int i = 0; i < H; i++) headers[i] = names[i % UNIQUE];
|
||||
|
||||
// correctness
|
||||
Map<String, List<Integer>> r1 = linkMultiHeaders_quadratic(headers);
|
||||
Map<String, List<Integer>> r2 = linkMultiHeaders_hash(headers);
|
||||
assert r1.keySet().equals(r2.keySet()) : "must produce same key set";
|
||||
for (String k : r1.keySet()) {
|
||||
assert r1.get(k).equals(r2.get(k)) :
|
||||
"chain mismatch for " + k + ": " + r1.get(k) + " vs " + r2.get(k);
|
||||
}
|
||||
|
||||
// performance
|
||||
int REPS = 10_000;
|
||||
long t0 = System.nanoTime();
|
||||
for (int r = 0; r < REPS; r++) linkMultiHeaders_quadratic(headers);
|
||||
long tQuad = System.nanoTime() - t0;
|
||||
|
||||
t0 = System.nanoTime();
|
||||
for (int r = 0; r < REPS; r++) linkMultiHeaders_hash(headers);
|
||||
long tHash = System.nanoTime() - t0;
|
||||
|
||||
double ratio = (double) tQuad / tHash;
|
||||
System.out.printf("nginx-0001: quadratic=%.3fs hash=%.3fs ratio=%.1f×%n",
|
||||
tQuad / 1e9, tHash / 1e9, ratio);
|
||||
assert ratio > 3 : "Expected >3× speedup, got " + ratio;
|
||||
System.out.println("PASS nginx-0001");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
testNginx0001();
|
||||
System.out.println("ALL PASS");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue