Superset: - superset-0001: SecurityManager._get_pvms_from_builtin_role pvm list dedup O(Regex*PVMs*R) HIGH 8x - superset-0002: DashboardDAO.update_native_filters_config filter dedup O(M*U) MEDIUM 40x - superset-0003: import_datasource metric/column dedup O(N^2) list rebuild MEDIUM 68x Metabase: CLEAN — Clojure backend uses sets/maps throughout for membership tests
207 lines
7.4 KiB
Java
207 lines
7.4 KiB
Java
import java.util.*;
|
|
|
|
/**
|
|
* CWE-407 simulation tests for Apache Superset defects.
|
|
*
|
|
* superset-0001: SecurityManager._get_pvms_from_builtin_role pvm dedup O(Regex*PVMs*R)
|
|
* superset-0002: DashboardDAO.update_native_filters_config filter dedup O(M*U)
|
|
* superset-0003: import_datasource metric/column dedup O(N^2) list rebuild
|
|
*/
|
|
public class SupersetTest {
|
|
|
|
// ---- superset-0001: builtin role PVM dedup ----
|
|
|
|
static List<Integer> getBuiltinRolePvmsBefore(int numRegex, int numPvms) {
|
|
// Simulates: for pvm_regex in regexes: for pvm in all_pvms: if pvm not in result_list
|
|
List<Integer> result = new ArrayList<>();
|
|
for (int r = 0; r < numRegex; r++) {
|
|
for (int p = 0; p < numPvms; p++) {
|
|
// Simulate regex match (every other one matches)
|
|
if ((r + p) % 2 == 0) {
|
|
if (!result.contains(p)) { // O(N) list scan
|
|
result.add(p);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static List<Integer> getBuiltinRolePvmsAfter(int numRegex, int numPvms) {
|
|
List<Integer> result = new ArrayList<>();
|
|
Set<Integer> seen = new HashSet<>();
|
|
for (int r = 0; r < numRegex; r++) {
|
|
for (int p = 0; p < numPvms; p++) {
|
|
if ((r + p) % 2 == 0) {
|
|
if (seen.add(p)) { // O(1) set lookup
|
|
result.add(p);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static boolean testSuperset0001() {
|
|
int numRegex = 20, numPvms = 2000;
|
|
|
|
long t0 = System.nanoTime();
|
|
List<Integer> before = getBuiltinRolePvmsBefore(numRegex, numPvms);
|
|
long tBefore = System.nanoTime() - t0;
|
|
|
|
t0 = System.nanoTime();
|
|
List<Integer> after = getBuiltinRolePvmsAfter(numRegex, numPvms);
|
|
long tAfter = System.nanoTime() - t0;
|
|
|
|
boolean sameResult = before.equals(after);
|
|
double ratio = (double) tBefore / tAfter;
|
|
|
|
System.out.printf("superset-0001: before=%,dns after=%,dns ratio=%.1fx match=%b%n",
|
|
tBefore, tAfter, ratio, sameResult);
|
|
return sameResult && ratio > 2.0;
|
|
}
|
|
|
|
// ---- superset-0002: dashboard filter dedup ----
|
|
|
|
static List<String> filterDedupBefore(List<String> existing, List<String> modified) {
|
|
List<Map<String, String>> updated = new ArrayList<>();
|
|
for (String id : existing) {
|
|
Map<String, String> m = new HashMap<>();
|
|
m.put("id", id);
|
|
updated.add(m);
|
|
}
|
|
for (String newId : modified) {
|
|
// Rebuild list comprehension every iteration: O(M*U)
|
|
List<String> updatedIds = new ArrayList<>();
|
|
for (Map<String, String> f : updated) {
|
|
updatedIds.add(f.get("id"));
|
|
}
|
|
if (!updatedIds.contains(newId)) {
|
|
Map<String, String> m = new HashMap<>();
|
|
m.put("id", newId);
|
|
updated.add(m);
|
|
}
|
|
}
|
|
List<String> result = new ArrayList<>();
|
|
for (Map<String, String> f : updated) result.add(f.get("id"));
|
|
return result;
|
|
}
|
|
|
|
static List<String> filterDedupAfter(List<String> existing, List<String> modified) {
|
|
List<Map<String, String>> updated = new ArrayList<>();
|
|
Set<String> updatedIds = new HashSet<>();
|
|
for (String id : existing) {
|
|
Map<String, String> m = new HashMap<>();
|
|
m.put("id", id);
|
|
updated.add(m);
|
|
updatedIds.add(id);
|
|
}
|
|
for (String newId : modified) {
|
|
if (!updatedIds.contains(newId)) { // O(1)
|
|
Map<String, String> m = new HashMap<>();
|
|
m.put("id", newId);
|
|
updated.add(m);
|
|
updatedIds.add(newId);
|
|
}
|
|
}
|
|
List<String> result = new ArrayList<>();
|
|
for (Map<String, String> f : updated) result.add(f.get("id"));
|
|
return result;
|
|
}
|
|
|
|
static boolean testSuperset0002() {
|
|
int N = 2000;
|
|
List<String> existing = new ArrayList<>();
|
|
List<String> modified = new ArrayList<>();
|
|
for (int i = 0; i < N; i++) {
|
|
existing.add("filter-" + i);
|
|
modified.add("filter-" + (N + i)); // all new
|
|
}
|
|
|
|
long t0 = System.nanoTime();
|
|
List<String> before = filterDedupBefore(existing, modified);
|
|
long tBefore = System.nanoTime() - t0;
|
|
|
|
t0 = System.nanoTime();
|
|
List<String> after = filterDedupAfter(existing, modified);
|
|
long tAfter = System.nanoTime() - t0;
|
|
|
|
boolean sameSize = before.size() == after.size();
|
|
double ratio = (double) tBefore / tAfter;
|
|
|
|
System.out.printf("superset-0002: before=%,dns after=%,dns ratio=%.1fx match=%b%n",
|
|
tBefore, tAfter, ratio, sameSize);
|
|
return sameSize && ratio > 2.0;
|
|
}
|
|
|
|
// ---- superset-0003: dataset import metric/column dedup ----
|
|
|
|
static List<String> importDedupBefore(List<String> importNames) {
|
|
List<String> datasourceNames = new ArrayList<>();
|
|
for (String name : importNames) {
|
|
// Rebuild list every iteration: O(N^2)
|
|
List<String> existing = new ArrayList<>(datasourceNames);
|
|
if (!existing.contains(name)) {
|
|
datasourceNames.add(name);
|
|
}
|
|
}
|
|
return datasourceNames;
|
|
}
|
|
|
|
static List<String> importDedupAfter(List<String> importNames) {
|
|
List<String> datasourceNames = new ArrayList<>();
|
|
Set<String> seen = new HashSet<>();
|
|
for (String name : importNames) {
|
|
if (seen.add(name)) { // O(1)
|
|
datasourceNames.add(name);
|
|
}
|
|
}
|
|
return datasourceNames;
|
|
}
|
|
|
|
static boolean testSuperset0003() {
|
|
int N = 5000;
|
|
List<String> importNames = new ArrayList<>();
|
|
for (int i = 0; i < N; i++) {
|
|
importNames.add("metric-" + i);
|
|
}
|
|
|
|
long t0 = System.nanoTime();
|
|
List<String> before = importDedupBefore(importNames);
|
|
long tBefore = System.nanoTime() - t0;
|
|
|
|
t0 = System.nanoTime();
|
|
List<String> after = importDedupAfter(importNames);
|
|
long tAfter = System.nanoTime() - t0;
|
|
|
|
boolean sameResult = before.equals(after);
|
|
double ratio = (double) tBefore / tAfter;
|
|
|
|
System.out.printf("superset-0003: before=%,dns after=%,dns ratio=%.1fx match=%b%n",
|
|
tBefore, tAfter, ratio, sameResult);
|
|
return sameResult && ratio > 2.0;
|
|
}
|
|
|
|
public static void main(String[] args) {
|
|
// Warmup
|
|
for (int i = 0; i < 3; i++) {
|
|
getBuiltinRolePvmsBefore(5, 100);
|
|
getBuiltinRolePvmsAfter(5, 100);
|
|
filterDedupBefore(List.of("a"), List.of("b"));
|
|
filterDedupAfter(List.of("a"), List.of("b"));
|
|
importDedupBefore(List.of("a", "b"));
|
|
importDedupAfter(List.of("a", "b"));
|
|
}
|
|
|
|
boolean p1 = testSuperset0001();
|
|
boolean p2 = testSuperset0002();
|
|
boolean p3 = testSuperset0003();
|
|
|
|
System.out.println();
|
|
System.out.println("superset-0001 (security PVM dedup): " + (p1 ? "PASS" : "FAIL"));
|
|
System.out.println("superset-0002 (dashboard filter dedup): " + (p2 ? "PASS" : "FAIL"));
|
|
System.out.println("superset-0003 (dataset import dedup): " + (p3 ? "PASS" : "FAIL"));
|
|
|
|
if (!p1 || !p2 || !p3) System.exit(1);
|
|
}
|
|
}
|