package unit; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * CWE-407 unit test: keystone-0001 * Implied-role deduplication: list comprehension vs set. * * Slow: `if imp_role_obj['id'] not in [x['id'] for x in roles]` * rebuilds list every check — O(n) per implied role. * Fast: maintain a seen_role_ids set — O(1) per check. */ public class KeystoneImpliedRoleAlgorithm { // Simulates the implied-role graph: role_id -> list of implied role_ids static Map> buildImpliedGraph(int R, int I) { Map> graph = new HashMap<>(); for (int i = 0; i < R; i++) { List implied = new ArrayList<>(); for (int j = 0; j < I; j++) { implied.add("implied-" + i + "-" + j); } graph.put("role-" + i, implied); // implied roles themselves have no further implications for (int j = 0; j < I; j++) { graph.put("implied-" + i + "-" + j, new ArrayList<>()); } } return graph; } // Defective: list comprehension for deduplication static long expandRolesSlow(List> roles, Map> impliedGraph) { long ops = 0; // NOTE: iterating over a mutable list that grows — simulating the defect for (int idx = 0; idx < roles.size(); idx++) { Map role = roles.get(idx); List implied = impliedGraph.getOrDefault(role.get("id"), new ArrayList<>()); for (String impId : implied) { ops++; // O(n) list scan — rebuild the id list each time boolean found = false; for (Map r : roles) { // O(current size) ops++; if (r.get("id").equals(impId)) { found = true; break; } } if (!found) { Map newRole = new HashMap<>(); newRole.put("id", impId); roles.add(newRole); } } } return ops; } // Fixed: set for deduplication static long expandRolesFast(List> roles, Map> impliedGraph) { long ops = 0; Set seenIds = new HashSet<>(); for (Map r : roles) seenIds.add(r.get("id")); List> snapshot = new ArrayList<>(roles); for (Map role : snapshot) { List implied = impliedGraph.getOrDefault(role.get("id"), new ArrayList<>()); for (String impId : implied) { ops++; if (!seenIds.contains(impId)) { // O(1) seenIds.add(impId); Map newRole = new HashMap<>(); newRole.put("id", impId); roles.add(newRole); } } } return ops; } static List> makeRoles(int count) { List> roles = new ArrayList<>(); for (int i = 0; i < count; i++) { Map r = new HashMap<>(); r.put("id", "role-" + i); roles.add(r); } return roles; } public static void main(String[] args) { int R = 50; // initial roles int I = 10; // implied roles per role int passed = 0; int total = 0; Map> graph = buildImpliedGraph(R, I); // Test 1: op count slow vs fast List> rolesSlow = makeRoles(R); List> rolesFast = makeRoles(R); long slowOps = expandRolesSlow(rolesSlow, graph); long fastOps = expandRolesFast(rolesFast, graph); total++; assert slowOps > fastOps * 5 : "slow=" + slowOps + " fast=" + fastOps + " speedup insufficient"; System.out.println("Test 1 PASS: implied-role expand slow=" + slowOps + " ops, fast=" + fastOps + " ops, speedup=" + (slowOps / Math.max(1, fastOps)) + "x"); passed++; // Test 2: correctness — same final role set Set slowIds = new HashSet<>(); for (Map r : rolesSlow) slowIds.add(r.get("id")); Set fastIds = new HashSet<>(); for (Map r : rolesFast) fastIds.add(r.get("id")); total++; assert slowIds.equals(fastIds) : "role sets differ: slow=" + slowIds.size() + " fast=" + fastIds.size(); System.out.println("Test 2 PASS: role sets agree (" + slowIds.size() + " roles)"); passed++; // Test 3: no duplicates in fast result total++; assert rolesFast.size() == fastIds.size() : "fast result contains duplicates: list=" + rolesFast.size() + " set=" + fastIds.size(); System.out.println("Test 3 PASS: no duplicates in fast result"); passed++; // Test 4: token_roles deduplication — list vs set // Simulate `token_roles = [r['id'] for r in token.roles]` + loop check List tokenRolesListBuild = new ArrayList<>(); for (int i = 0; i < R; i++) tokenRolesListBuild.add("role-" + i); Set tokenRolesSet = new HashSet<>(tokenRolesListBuild); long listCheckOps = 0; long setCheckOps = 0; List> allRoles = makeRoles(R * 2); // some not in token for (Map role : allRoles) { listCheckOps += tokenRolesListBuild.size(); // O(T) list scan setCheckOps++; // O(1) set lookup @SuppressWarnings("unused") boolean listContains = tokenRolesListBuild.contains(role.get("id")); @SuppressWarnings("unused") boolean setContains = tokenRolesSet.contains(role.get("id")); } total++; assert listCheckOps > setCheckOps * 5 : "token_roles: list=" + listCheckOps + " set=" + setCheckOps; System.out.println("Test 4 PASS: token_roles list=" + listCheckOps + " ops, set=" + setCheckOps + " ops"); passed++; System.out.println(passed + "/" + total + " PASS"); } }