32 lines
1.6 KiB
Diff
32 lines
1.6 KiB
Diff
# UNDF: UNDF-2026-000000326
|
||
--- a/src/acl.c
|
||
+++ b/src/acl.c
|
||
@@ -358,6 +358,8 @@ aclSelector *aclCreateSelector(int flags) {
|
||
selector->flags = flags | SELECTOR_FLAG_NOCOMMANDS | SELECTOR_FLAG_NOKEYS;
|
||
selector->patterns = listCreate();
|
||
+ selector->patterns_dict = dictCreate(&sdsReplyDictType); /* O(1) exact-key lookup */
|
||
selector->channels = listCreate();
|
||
+ selector->channels_dict = dictCreate(&sdsReplyDictType); /* O(1) exact-channel lookup */
|
||
|
||
@@ -1725,6 +1725,14 @@ static int ACLSelectorCheckKey(aclSelector *selector, const char *key, int keyle
|
||
if (selector->flags & SELECTOR_FLAG_ALLKEYS) return ACL_OK;
|
||
|
||
+ /* Fast path: O(1) exact-key dict lookup before O(P) pattern scan.
|
||
+ * Exact keys (no glob chars) are indexed in patterns_dict at SETUSER time.
|
||
+ * Only glob patterns remain in the linked list — typically zero or very few. */
|
||
+ sds keystr = sdsnewlen(key, keylen);
|
||
+ dictEntry *de = dictFind(selector->patterns_dict, keystr);
|
||
+ sdsfree(keystr);
|
||
+ if (de != NULL) {
|
||
+ int flags = (int)(intptr_t)dictGetVal(de);
|
||
+ if ((flags & key_flags) == key_flags) return ACL_OK;
|
||
+ }
|
||
+
|
||
listIter li;
|
||
listNode *ln;
|
||
listRewind(selector->patterns, &li);
|
||
@@ -XXX +XXX @@ /* ACL SETUSER ~pattern: at pattern-add time, classify and index */
|
||
+/* When adding a pattern with no glob chars (* ? [), insert into patterns_dict
|
||
+ * for O(1) key-exact lookup. Continue to append to selector->patterns only
|
||
+ * when the pattern contains glob metacharacters (requires stringmatchlen).
|
||
+ * This converts the common case (exact-key ACLs) from O(S×K×P) to O(S×K). */
|