578/240 — rustc-0004/vertx-0001/asterisk-0003/bitcoin-0001/actix-web-0003/hazelcast-0001+0002/rabbitmq-0005/nginx-0003/haproxy-0003/envoy-0003/istio-0003
This commit is contained in:
parent
dde5ec97fb
commit
e4ee168b1e
50 changed files with 4775 additions and 5 deletions
172
defects/actix/unit/ActixUpdateUniqueAlgorithm.java
Normal file
172
defects/actix/unit/ActixUpdateUniqueAlgorithm.java
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
package unit;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* actix-0001: CWE-407 actix-web introspection update_unique O(R×G) Vec linear dedup.
|
||||
*
|
||||
* Simulates the defective update_unique() pattern from actix-web's
|
||||
* introspection.rs:984-989:
|
||||
*
|
||||
* fn update_unique<T>(existing: &mut Vec<T>, new_items: &[T]) {
|
||||
* for item in new_items {
|
||||
* if !existing.contains(item) { // O(E) linear scan
|
||||
* existing.push(item.clone());
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* Called once per route registration for guards, patterns, and methods vecs.
|
||||
* With R routes sharing a scope and G unique guards accumulating, total work
|
||||
* is O(R × G).
|
||||
*
|
||||
* Fix: pre-build a HashSet for O(1) membership, reducing to O(R + G).
|
||||
*/
|
||||
public class ActixUpdateUniqueAlgorithm {
|
||||
|
||||
static long slowOps = 0;
|
||||
static long fastOps = 0;
|
||||
|
||||
// --- SLOW: Vec.contains() linear scan (actix-web defective pattern) ---
|
||||
|
||||
static void updateUniqueSlow(List<String> existing, List<String> newItems) {
|
||||
for (String item : newItems) {
|
||||
slowOps++;
|
||||
boolean found = false;
|
||||
for (String e : existing) { // O(E) inner scan
|
||||
slowOps++;
|
||||
if (e.equals(item)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
existing.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- FAST: HashSet membership check O(1) per item ---
|
||||
|
||||
static void updateUniqueFast(List<String> existing, Set<String> existingSet, List<String> newItems) {
|
||||
for (String item : newItems) {
|
||||
fastOps++;
|
||||
if (!existingSet.contains(item)) {
|
||||
existing.add(item);
|
||||
existingSet.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Simulate R route registrations, each contributing G guard names to a shared path's accumulator.
|
||||
// In actix-web: register_pattern_detail() calls update_unique() for guards on each route.
|
||||
static List<String> simulateSlow(int R, int G) {
|
||||
List<String> accumulated = new ArrayList<>();
|
||||
for (int r = 0; r < R; r++) {
|
||||
List<String> routeGuards = new ArrayList<>();
|
||||
for (int g = 0; g < G; g++) {
|
||||
// Routes share some guards + add one unique guard each
|
||||
routeGuards.add("guard_" + (g % (G / 2 + 1)));
|
||||
}
|
||||
routeGuards.add("route_guard_" + r);
|
||||
updateUniqueSlow(accumulated, routeGuards);
|
||||
}
|
||||
return accumulated;
|
||||
}
|
||||
|
||||
static List<String> simulateFast(int R, int G) {
|
||||
List<String> accumulated = new ArrayList<>();
|
||||
Set<String> accumulatedSet = new HashSet<>();
|
||||
for (int r = 0; r < R; r++) {
|
||||
List<String> routeGuards = new ArrayList<>();
|
||||
for (int g = 0; g < G; g++) {
|
||||
routeGuards.add("guard_" + (g % (G / 2 + 1)));
|
||||
}
|
||||
routeGuards.add("route_guard_" + r);
|
||||
updateUniqueFast(accumulated, accumulatedSet, routeGuards);
|
||||
}
|
||||
return accumulated;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("actix-0001: update_unique O(R×G) Vec linear dedup vs HashSet");
|
||||
System.out.println("=============================================================");
|
||||
|
||||
int[] sizes = {50, 100, 200, 500};
|
||||
int passes = 0;
|
||||
int failures = 0;
|
||||
|
||||
for (int N : sizes) {
|
||||
slowOps = 0;
|
||||
fastOps = 0;
|
||||
|
||||
int R = N; // routes sharing a scope
|
||||
int G = 20; // guards per route registration
|
||||
|
||||
List<String> slowResult = simulateSlow(R, G);
|
||||
List<String> fastResult = simulateFast(R, G);
|
||||
|
||||
// Sort both for comparison
|
||||
List<String> sortedSlow = new ArrayList<>(slowResult);
|
||||
List<String> sortedFast = new ArrayList<>(fastResult);
|
||||
Collections.sort(sortedSlow);
|
||||
Collections.sort(sortedFast);
|
||||
|
||||
boolean match = sortedSlow.equals(sortedFast);
|
||||
double ratio = slowOps > 0 ? (double) slowOps / Math.max(fastOps, 1) : 0;
|
||||
|
||||
String status = (match && ratio >= 5.0) ? "PASS" : "FAIL";
|
||||
System.out.printf(" N=%3d routes, G=%2d guards/reg: slow=%7d ops fast=%6d ops ratio=%.1fx result_match=%s [%s]%n",
|
||||
R, G, slowOps, fastOps, ratio, match, status);
|
||||
|
||||
if (match && ratio >= 5.0) {
|
||||
passes++;
|
||||
} else {
|
||||
failures++;
|
||||
if (!match) {
|
||||
System.out.println(" ERROR: slow and fast results differ!");
|
||||
System.out.println(" slow size=" + sortedSlow.size() + " fast size=" + sortedFast.size());
|
||||
}
|
||||
if (ratio < 5.0) {
|
||||
System.out.printf(" ERROR: ratio %.1fx below required 5x minimum%n", ratio);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
|
||||
// Larger test: G=50 guards per route (high guard density scenario)
|
||||
System.out.println("High-density guard test (R=500, G=50 guards/reg):");
|
||||
{
|
||||
int R = 500;
|
||||
int G = 50;
|
||||
slowOps = 0;
|
||||
fastOps = 0;
|
||||
|
||||
List<String> slowResult = simulateSlow(R, G);
|
||||
List<String> fastResult = simulateFast(R, G);
|
||||
|
||||
List<String> sortedSlow = new ArrayList<>(slowResult);
|
||||
List<String> sortedFast = new ArrayList<>(fastResult);
|
||||
Collections.sort(sortedSlow);
|
||||
Collections.sort(sortedFast);
|
||||
|
||||
boolean match = sortedSlow.equals(sortedFast);
|
||||
double ratio = (double) slowOps / Math.max(fastOps, 1);
|
||||
String status = (match && ratio >= 5.0) ? "PASS" : "FAIL";
|
||||
|
||||
System.out.printf(" R=%d routes, G=%d: slow=%d ops fast=%d ops ratio=%.1fx match=%s [%s]%n",
|
||||
R, G, slowOps, fastOps, ratio, match, status);
|
||||
|
||||
if (match && ratio >= 5.0) passes++;
|
||||
else failures++;
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.printf("%d/%d PASS%n", passes, passes + failures);
|
||||
|
||||
if (failures > 0) {
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue