import java.util.*; /** * CWE-407 unit tests for Dragonfly ACL validator.cc defects. * * dragonfly-0001: src/server/acl/validator.cc IsUserAllowedToInvokeCommandGeneric() * key_globs is std::vector — O(G) linear scan per key per command. * At K=500 keys (MSET) × G=50 globs: 25,000 Matches() calls per command. * Fix: split into exact_keys map (O(1)) + glob-only vector (typically empty). * * dragonfly-0002: src/server/acl/validator.cc IsPubSubCommandAuthorized() * pub_sub.globs is std::vector — O(G) scan per SUBSCRIBE arg. * Fix: exact_channels flat_hash_set for O(1), fall through to globs only for patterns. */ public class DragonflyTest { // --- dragonfly-0001 --- static boolean containsKey_vector(List keyGlobs, String key) { for (String g : keyGlobs) { // O(G) — defect if (key.equals(g)) return true; // simplified: no glob matching } return false; } static boolean containsKey_map(Map exactKeys, List globPatterns, String key) { if (exactKeys.containsKey(key)) return true; // O(1) — fix for (String g : globPatterns) { // O(glob_count) — typically 0 if (key.equals(g)) return true; } return false; } static void testDragonfly0001() throws Exception { int G = 100; // ACL key glob patterns configured int K = 500; // keys in one MSET command List keyGlobs = new ArrayList<>(G); Map exactKeys = new HashMap<>(G); for (int i = 0; i < G; i++) { String pattern = "key:" + i; keyGlobs.add(pattern); exactKeys.put(pattern, Boolean.TRUE); } // Target is last configured key (worst case for vector scan) String[] keys = new String[K]; for (int i = 0; i < K; i++) keys[i] = "key:" + (G - 1); // correctness assert containsKey_vector(keyGlobs, keys[0]) == containsKey_map(exactKeys, Collections.emptyList(), keys[0]); assert !containsKey_vector(keyGlobs, "unknown") && !containsKey_map(exactKeys, Collections.emptyList(), "unknown"); // performance: simulate one MSET with K keys int REPS = 5000; long t0 = System.nanoTime(); for (int r = 0; r < REPS; r++) { for (String k : keys) containsKey_vector(keyGlobs, k); } long tVec = System.nanoTime() - t0; t0 = System.nanoTime(); for (int r = 0; r < REPS; r++) { for (String k : keys) containsKey_map(exactKeys, Collections.emptyList(), k); } long tMap = System.nanoTime() - t0; double ratio = (double) tVec / tMap; System.out.printf("dragonfly-0001: vector=%.3fs map=%.3fs ratio=%.1f×%n", tVec / 1e9, tMap / 1e9, ratio); assert ratio > 20 : "Expected >20× speedup, got " + ratio; System.out.println("PASS dragonfly-0001"); } // --- dragonfly-0002 --- static boolean channelAllowed_vector(List globs, String channel) { for (String g : globs) { // O(G) — defect if (channel.equals(g)) return true; } return false; } static boolean channelAllowed_set(Set exactChannels, List globs, String channel) { if (exactChannels.contains(channel)) return true; // O(1) — fix for (String g : globs) return channel.equals(g); return false; } static void testDragonfly0002() throws Exception { int G = 100; // ACL pub/sub glob patterns int A = 200; // channels in one SUBSCRIBE command List globs = new ArrayList<>(G); Set exactChannels = new HashSet<>(G); for (int i = 0; i < G; i++) { String ch = "ch:" + i; globs.add(ch); exactChannels.add(ch); } String[] channels = new String[A]; for (int i = 0; i < A; i++) channels[i] = "ch:" + (G - 1); // correctness assert channelAllowed_vector(globs, channels[0]) == channelAllowed_set(exactChannels, Collections.emptyList(), channels[0]); int REPS = 5000; long t0 = System.nanoTime(); for (int r = 0; r < REPS; r++) { for (String ch : channels) channelAllowed_vector(globs, ch); } long tVec = System.nanoTime() - t0; t0 = System.nanoTime(); for (int r = 0; r < REPS; r++) { for (String ch : channels) channelAllowed_set(exactChannels, Collections.emptyList(), ch); } long tSet = System.nanoTime() - t0; double ratio = (double) tVec / tSet; System.out.printf("dragonfly-0002: vector=%.3fs set=%.3fs ratio=%.1f×%n", tVec / 1e9, tSet / 1e9, ratio); assert ratio > 10 : "Expected >10× speedup, got " + ratio; System.out.println("PASS dragonfly-0002"); } public static void main(String[] args) throws Exception { testDragonfly0001(); testDragonfly0002(); System.out.println("ALL PASS"); } }