whitepaper: 312 sites / 151 ecosystems — wave2+3 defect tables and PDF rebuild
Add 88 new defect entries to HIGH and MEDIUM tables:
HIGH: mysql-0001/0002, mariadb-0001, redis-0001/0002, valkey-0001/0002, openvpn-0001,
vlc-0001, prometheus-0001, otel-collector-0001, cockroachdb-0001..0004,
tidb-0001..0008, kubernetes-0001/0002, go-0001, kotlin-0002, scala-0001,
allegro5-0001, sdl2-0001, grafana-0001, clickhouse-0001, duckdb-0001,
mongodb-0001, envoy-0001, istio-0001, cilium-0001, linkerd2-0001,
linux-0001/0002/0003, tor-0002/0003, curl-0001, julia-0001, lua-0001,
perl5-0001, nats-0001, spring-0003/0004, tomcat-0001, onos-0002, odl-0002
MEDIUM: helm-0001, mariadb-0002, openssl-0001/0002, memcached-0001,
cassandra-0001..0004, flink-0001, storm-0001/0002, zookeeper-0001..0003,
pip-0001, gradle-0001, nginx-0001, haproxy-0001, caddy-0001, varnish-0001,
ffmpeg-0001, gstreamer-0001, raylib-0001, love2d-0001, php-0001/0002,
r-source-0001, cpython-0002, ruby-0001, rabbitmq-0003/0004, activemq-0001,
ovs-0001, onos-0003, odl-0002, jetty-0001
PDF: 976K
This commit is contained in:
parent
b3842ab6b8
commit
9934133dcf
260 changed files with 18278 additions and 15 deletions
207
defects/mysql/unit/MysqlTest.java
Normal file
207
defects/mysql/unit/MysqlTest.java
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
package unit;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* MysqlTest — CWE-407 benchmarks for MySQL defects.
|
||||
*
|
||||
* mysql-0001: SHOW GRANTS USING roles — O(U*G) vector find vs O(U) hash lookup
|
||||
* mysql-0002: has_global_grant fallback — O(P) multimap equal_range+find vs O(1) map lookup
|
||||
*
|
||||
* No JUnit. Prints N/N PASS.
|
||||
*/
|
||||
public class MysqlTest {
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Harness
|
||||
// -----------------------------------------------------------------------
|
||||
static void bench(String label, Runnable slow, Runnable fast, long sOps, long fOps) {
|
||||
slow.run(); fast.run();
|
||||
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;
|
||||
System.out.printf(" %-60s slow:%4dms (%,d ops) fast:%4dms (%,d ops) speedup:%.0fx%n",
|
||||
label, sMs, sOps, fMs, fOps, fOps > 0 ? (double) sOps / fOps : 0);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// mysql-0001 — SHOW GRANTS USING: vector find vs unordered_set
|
||||
//
|
||||
// Models sql/auth/sql_authorization.cc:4875-4898
|
||||
// Outer loop: using_roles (U entries)
|
||||
// Inner: std::find on granted_roles vector (G entries) — O(G) per iter
|
||||
// Inner: std::find_if on mandatory_roles vector (M entries) — O(M) per iter
|
||||
// Total: O(U * (G + M))
|
||||
//
|
||||
// Fix: build unordered_set<string> from granted_roles + mandatory_roles before loop
|
||||
// Total: O(G + M) setup + O(U) lookups
|
||||
// -----------------------------------------------------------------------
|
||||
static long[] showGrantsSlow(int U, int G, int M) {
|
||||
// granted_roles: vector of pairs (authid, with_admin)
|
||||
List<String[]> grantedRoles = new ArrayList<>(G);
|
||||
for (int i = 0; i < G; i++) grantedRoles.add(new String[]{"role_granted_" + i});
|
||||
|
||||
// mandatory_roles: vector of Role_id
|
||||
List<String> mandatoryRoles = new ArrayList<>(M);
|
||||
for (int i = 0; i < M; i++) mandatoryRoles.add("role_mandatory_" + i);
|
||||
|
||||
// using_roles: request to activate U roles (last one is a granted role, rest miss)
|
||||
List<String> usingRoles = new ArrayList<>(U);
|
||||
for (int i = 0; i < U - 1; i++) usingRoles.add("role_granted_" + i); // found in granted
|
||||
if (U > 0) usingRoles.add("role_mandatory_0"); // found in mandatory
|
||||
|
||||
long ops = 0;
|
||||
for (String authid : usingRoles) {
|
||||
// O(G) linear find on granted_roles vector
|
||||
boolean foundInGranted = false;
|
||||
for (String[] gr : grantedRoles) {
|
||||
ops++;
|
||||
if (gr[0].equals(authid)) { foundInGranted = true; break; }
|
||||
}
|
||||
if (!foundInGranted) {
|
||||
// O(M) linear find on mandatory_roles vector
|
||||
for (String rid : mandatoryRoles) {
|
||||
ops++;
|
||||
if (rid.equals(authid)) { break; }
|
||||
}
|
||||
}
|
||||
}
|
||||
return new long[]{ops};
|
||||
}
|
||||
|
||||
static long[] showGrantsFast(int U, int G, int M) {
|
||||
List<String[]> grantedRoles = new ArrayList<>(G);
|
||||
for (int i = 0; i < G; i++) grantedRoles.add(new String[]{"role_granted_" + i});
|
||||
|
||||
List<String> mandatoryRoles = new ArrayList<>(M);
|
||||
for (int i = 0; i < M; i++) mandatoryRoles.add("role_mandatory_" + i);
|
||||
|
||||
List<String> usingRoles = new ArrayList<>(U);
|
||||
for (int i = 0; i < U - 1; i++) usingRoles.add("role_granted_" + i);
|
||||
if (U > 0) usingRoles.add("role_mandatory_0");
|
||||
|
||||
long ops = 0;
|
||||
// Build O(1) sets before the loop — the fix
|
||||
Set<String> grantedSet = new HashSet<>(G * 2);
|
||||
for (String[] gr : grantedRoles) { grantedSet.add(gr[0]); ops++; }
|
||||
Set<String> mandatorySet = new HashSet<>(M * 2);
|
||||
for (String rid : mandatoryRoles) { mandatorySet.add(rid); ops++; }
|
||||
|
||||
for (String authid : usingRoles) {
|
||||
ops++; // O(1) hash lookup
|
||||
if (!grantedSet.contains(authid)) {
|
||||
ops++; // O(1) hash lookup
|
||||
grantedSet.contains(authid); // suppress
|
||||
mandatorySet.contains(authid);
|
||||
}
|
||||
}
|
||||
return new long[]{ops};
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// mysql-0002 — has_global_grant fallback: O(P) std::find vs O(1) map
|
||||
//
|
||||
// Models sql/auth/sql_security_ctx.cc:735-740
|
||||
// equal_range returns P entries for this user in the multimap
|
||||
// std::find walks all P entries to find the privilege string
|
||||
// Called Q times (Q queries checking this user's privileges)
|
||||
// Total: O(Q * P)
|
||||
//
|
||||
// Fix: build local unordered_map<string,bool> from equal_range once per
|
||||
// security context refresh — O(P) setup + O(Q) lookups
|
||||
// -----------------------------------------------------------------------
|
||||
static long[] hasGlobalGrantSlow(int P, int Q) {
|
||||
// P dynamic privileges for one user in the multimap equal_range
|
||||
List<String[]> equalRange = new ArrayList<>(P);
|
||||
for (int i = 0; i < P; i++) equalRange.add(new String[]{"PRIV_" + i, "false"});
|
||||
|
||||
// Target privilege is always the last one (worst case O(P))
|
||||
String target = "PRIV_" + (P - 1);
|
||||
|
||||
long ops = 0;
|
||||
for (int q = 0; q < Q; q++) {
|
||||
// O(P) std::find scan
|
||||
for (String[] entry : equalRange) {
|
||||
ops++;
|
||||
if (entry[0].equals(target)) break;
|
||||
}
|
||||
}
|
||||
return new long[]{ops};
|
||||
}
|
||||
|
||||
static long[] hasGlobalGrantFast(int P, int Q) {
|
||||
List<String[]> equalRange = new ArrayList<>(P);
|
||||
for (int i = 0; i < P; i++) equalRange.add(new String[]{"PRIV_" + i, "false"});
|
||||
|
||||
String target = "PRIV_" + (P - 1);
|
||||
|
||||
long ops = 0;
|
||||
// Build local unordered_map once (models per-context-refresh caching)
|
||||
Map<String, Boolean> localMap = new HashMap<>(P * 2);
|
||||
for (String[] entry : equalRange) {
|
||||
localMap.put(entry[0], Boolean.parseBoolean(entry[1]));
|
||||
ops++; // map build cost
|
||||
}
|
||||
|
||||
for (int q = 0; q < Q; q++) {
|
||||
ops++; // O(1) hash lookup
|
||||
localMap.containsKey(target);
|
||||
}
|
||||
return new long[]{ops};
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Main
|
||||
// -----------------------------------------------------------------------
|
||||
public static void main(String[] args) {
|
||||
System.out.println("mysql CWE-407 benchmarks");
|
||||
System.out.println("=".repeat(100));
|
||||
|
||||
int failures = 0;
|
||||
int total = 0;
|
||||
|
||||
// --- mysql-0001 ---
|
||||
{
|
||||
int U = 500, G = 500, M = 100;
|
||||
long[] slowOps = new long[1], fastOps = new long[1];
|
||||
|
||||
Runnable slow = () -> { long[] r = showGrantsSlow(U, G, M); slowOps[0] = r[0]; };
|
||||
Runnable fast = () -> { long[] r = showGrantsFast(U, G, M); fastOps[0] = r[0]; };
|
||||
|
||||
slow.run(); fast.run();
|
||||
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 speedup = fastOps[0] > 0 ? (double) slowOps[0] / fastOps[0] : 0;
|
||||
System.out.printf(" %-60s slow:%4dms (%,d ops) fast:%4dms (%,d ops) speedup:%.1fx%n",
|
||||
"mysql-0001 SHOW GRANTS USING roles O(U*G) vs O(U)", sMs, slowOps[0], fMs, fastOps[0], speedup);
|
||||
|
||||
total++;
|
||||
boolean pass = slowOps[0] > fastOps[0] * 5L;
|
||||
if (!pass) { System.out.println(" FAIL: expected slowOps > fastOps * 5"); failures++; }
|
||||
}
|
||||
|
||||
// --- mysql-0002 ---
|
||||
{
|
||||
int P = 500, Q = 1000;
|
||||
long[] slowOps = new long[1], fastOps = new long[1];
|
||||
|
||||
Runnable slow = () -> { long[] r = hasGlobalGrantSlow(P, Q); slowOps[0] = r[0]; };
|
||||
Runnable fast = () -> { long[] r = hasGlobalGrantFast(P, Q); fastOps[0] = r[0]; };
|
||||
|
||||
slow.run(); fast.run();
|
||||
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 speedup = fastOps[0] > 0 ? (double) slowOps[0] / fastOps[0] : 0;
|
||||
System.out.printf(" %-60s slow:%4dms (%,d ops) fast:%4dms (%,d ops) speedup:%.1fx%n",
|
||||
"mysql-0002 has_global_grant O(P*Q) vs O(P+Q)", sMs, slowOps[0], fMs, fastOps[0], speedup);
|
||||
|
||||
total++;
|
||||
// slow: Q*P ops; fast: P + Q ops; ratio ~ Q*P / (P+Q) ~ Q/2 at equal P,Q
|
||||
boolean pass = slowOps[0] > fastOps[0] * 10L;
|
||||
if (!pass) { System.out.println(" FAIL: expected slowOps > fastOps * 10"); failures++; }
|
||||
}
|
||||
|
||||
System.out.println("=".repeat(100));
|
||||
System.out.printf("%d/%d %s%n", total - failures, total, failures == 0 ? "PASS" : "FAIL");
|
||||
if (failures > 0) System.exit(1);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue