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
175
defects/grape/unit/GrapeAlgorithm.java
Normal file
175
defects/grape/unit/GrapeAlgorithm.java
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
package unit;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* GrapeAlgorithm — grape-0001..0003
|
||||
*
|
||||
* Proves CWE-407 in Grape (Ruby API framework):
|
||||
* grape-0001: ValuesValidator — values Array#include? in param_array.all? O(P×V)
|
||||
* grape-0002: ExceptValuesValidator — excepts Array#include? in param_array.any? O(P×E)
|
||||
* grape-0003: DSL::Routing#route — endpoints Array#any? duplicate check O(N²)
|
||||
*
|
||||
* Run: javac -d . GrapeAlgorithm.java && java -ea unit.GrapeAlgorithm
|
||||
*/
|
||||
public class GrapeAlgorithm {
|
||||
|
||||
// ── grape-0001: ValuesValidator values.include? ───────────────────────────
|
||||
|
||||
/** SLOW: values is Array — Array#include? per param O(P×V) */
|
||||
static long valuesValidatorSlow(int paramCount, int valuesCount) {
|
||||
// Build allowlist array (e.g., permitted tag values)
|
||||
List<String> valuesArr = new ArrayList<>();
|
||||
for (int i = 0; i < valuesCount; i++) valuesArr.add("value_" + i);
|
||||
|
||||
long ops = 0;
|
||||
// Simulate P submitted params, each validated against V-element array
|
||||
// param_array.all? { |param| values.include?(param) }
|
||||
for (int p = 0; p < paramCount; p++) {
|
||||
String param = "value_" + (p % valuesCount);
|
||||
for (String v : valuesArr) {
|
||||
ops++;
|
||||
if (v.equals(param)) break; // include? short-circuits but worst case scans all
|
||||
}
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
/** FAST: values is Set — Set#include? per param O(P+V) */
|
||||
static long valuesValidatorFast(int paramCount, int valuesCount) {
|
||||
// values_set = values.to_set
|
||||
Set<String> valuesSet = new HashSet<>();
|
||||
for (int i = 0; i < valuesCount; i++) valuesSet.add("value_" + i);
|
||||
|
||||
long ops = 0;
|
||||
for (int p = 0; p < paramCount; p++) {
|
||||
String param = "value_" + (p % valuesCount);
|
||||
ops++; // O(1) Set#include?
|
||||
valuesSet.contains(param);
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
// ── grape-0002: ExceptValuesValidator excepts.include? ───────────────────
|
||||
|
||||
/** SLOW: excepts is Array — Array#include? per param O(P×E) */
|
||||
static long exceptValuesValidatorSlow(int paramCount, int exceptsCount) {
|
||||
// Build blocklist array (e.g., reserved words that cannot be submitted)
|
||||
List<String> exceptsArr = new ArrayList<>();
|
||||
for (int i = 0; i < exceptsCount; i++) exceptsArr.add("except_" + i);
|
||||
|
||||
long ops = 0;
|
||||
// Simulate P submitted params; raise if any is in blocklist
|
||||
// param_array.any? { |param| excepts.include?(param) }
|
||||
for (int p = 0; p < paramCount; p++) {
|
||||
String param = "safe_" + p; // none match, forces full scan each time
|
||||
for (String e : exceptsArr) {
|
||||
ops++;
|
||||
if (e.equals(param)) break;
|
||||
}
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
/** FAST: excepts is Set — Set#include? per param O(P+E) */
|
||||
static long exceptValuesValidatorFast(int paramCount, int exceptsCount) {
|
||||
Set<String> exceptsSet = new HashSet<>();
|
||||
for (int i = 0; i < exceptsCount; i++) exceptsSet.add("except_" + i);
|
||||
|
||||
long ops = 0;
|
||||
for (int p = 0; p < paramCount; p++) {
|
||||
String param = "safe_" + p;
|
||||
ops++; // O(1) Set#include?
|
||||
exceptsSet.contains(param);
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
// ── grape-0003: DSL::Routing endpoints duplicate check ───────────────────
|
||||
|
||||
/**
|
||||
* SLOW: endpoints is Array — endpoints.any? { |e| e.equals?(new_endpoint) }
|
||||
* O(N²) total across N route registrations
|
||||
*/
|
||||
static long routingEndpointsSlow(int routeCount) {
|
||||
List<String> endpoints = new ArrayList<>();
|
||||
long ops = 0;
|
||||
for (int i = 0; i < routeCount; i++) {
|
||||
String newEndpoint = "GET:/path/" + i;
|
||||
// endpoints.any? { |e| e.equals?(new_endpoint) }
|
||||
boolean found = false;
|
||||
for (String e : endpoints) {
|
||||
ops++;
|
||||
if (e.equals(newEndpoint)) { found = true; break; }
|
||||
}
|
||||
if (!found) endpoints.add(newEndpoint);
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
/**
|
||||
* FAST: endpoints seen in Hash — Hash#key? per registration O(N)
|
||||
*/
|
||||
static long routingEndpointsFast(int routeCount) {
|
||||
List<String> endpoints = new ArrayList<>();
|
||||
Map<String, Boolean> endpointsSeen = new HashMap<>();
|
||||
long ops = 0;
|
||||
for (int i = 0; i < routeCount; i++) {
|
||||
String newEndpoint = "GET:/path/" + i;
|
||||
ops++; // O(1) Hash#key?
|
||||
if (!endpointsSeen.containsKey(newEndpoint)) {
|
||||
endpointsSeen.put(newEndpoint, true);
|
||||
endpoints.add(newEndpoint);
|
||||
}
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
// ── bench harness ─────────────────────────────────────────────────────────
|
||||
|
||||
interface Bench { long run(); }
|
||||
|
||||
static void bench(String label, Bench slow, Bench fast, long sOps, long fOps) {
|
||||
long t0 = System.nanoTime(); slow.run(); long sMs = (System.nanoTime()-t0)/1_000_000;
|
||||
long t1 = System.nanoTime(); fast.run(); long fMs = (System.nanoTime()-t1)/1_000_000;
|
||||
double r = fOps > 0 ? (double)sOps/fOps : 0;
|
||||
System.out.printf(" %-52s slow:%4dms (%,d ops) fast:%4dms (%,d ops) speedup:%.0fx%n",
|
||||
label, sMs, sOps, fMs, fOps, r);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("=== UNIT grape-0001..0003: Grape CWE-407 ===");
|
||||
System.out.println();
|
||||
|
||||
final int PARAMS = 100, VALUES = 300; // grape-0001: 100 submitted, 300 allowed
|
||||
final int PARAMS2 = 80, EXCEPTS = 200; // grape-0002: 80 submitted, 200 blocklisted
|
||||
final int ROUTES = 600; // grape-0003: 600 route registrations
|
||||
|
||||
long s0 = valuesValidatorSlow(PARAMS, VALUES);
|
||||
long f0 = valuesValidatorFast(PARAMS, VALUES);
|
||||
bench("grape-0001 ValuesValidator values.include?",
|
||||
() -> valuesValidatorSlow(PARAMS, VALUES),
|
||||
() -> valuesValidatorFast(PARAMS, VALUES), s0, f0);
|
||||
|
||||
long s1 = exceptValuesValidatorSlow(PARAMS2, EXCEPTS);
|
||||
long f1 = exceptValuesValidatorFast(PARAMS2, EXCEPTS);
|
||||
bench("grape-0002 ExceptValuesValidator excepts.include?",
|
||||
() -> exceptValuesValidatorSlow(PARAMS2, EXCEPTS),
|
||||
() -> exceptValuesValidatorFast(PARAMS2, EXCEPTS), s1, f1);
|
||||
|
||||
long s2 = routingEndpointsSlow(ROUTES);
|
||||
long f2 = routingEndpointsFast(ROUTES);
|
||||
bench("grape-0003 DSL::Routing endpoints.any? dup check",
|
||||
() -> routingEndpointsSlow(ROUTES),
|
||||
() -> routingEndpointsFast(ROUTES), s2, f2);
|
||||
|
||||
System.out.println();
|
||||
int pass = 0;
|
||||
assert s0 > f0 * 5 : "grape-0001 expected >5x speedup; got slow=" + s0 + " fast=" + f0; pass++;
|
||||
assert s1 > f1 * 5 : "grape-0002 expected >5x speedup; got slow=" + s1 + " fast=" + f1; pass++;
|
||||
assert s2 > f2 * 5 : "grape-0003 expected >5x speedup; got slow=" + s2 + " fast=" + f2; pass++;
|
||||
|
||||
System.out.printf("%d/3 PASS — grape-0001..0003: CWE-407 in ValuesValidator/ExceptValuesValidator/DSL::Routing%n", pass);
|
||||
System.out.printf("Hotpaths: per-request param validation (grape-0001/0002), app boot route registration (grape-0003)%n");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue