39 lines
1.7 KiB
Diff
39 lines
1.7 KiB
Diff
# UNDF: UNDF-2026-000000382
|
||
--- a/src/server/acl/acl_commands_def.h
|
||
+++ b/src/server/acl/acl_commands_def.h
|
||
@@ -78,7 +78,8 @@ using GlobType = std::pair<std::string, KeyOp>;
|
||
struct AclKeys {
|
||
- std::vector<GlobType> key_globs; // O(G) scan per key per command — defect
|
||
+ std::vector<GlobType> key_globs; // kept for glob patterns (require Matches())
|
||
+ absl::flat_hash_map<std::string, KeyOp> exact_keys; // O(1) lookup for non-glob patterns
|
||
|
||
--- a/src/server/acl/validator.cc
|
||
+++ b/src/server/acl/validator.cc
|
||
@@ -127,10 +127,20 @@ IsUserAllowedToInvokeCommandGeneric(...) {
|
||
auto iterate_globs = [&](auto target) {
|
||
+ /* First check exact-key map — O(1) */
|
||
+ auto it = keys.exact_keys.find(std::string(target));
|
||
+ if (it != keys.exact_keys.end()) {
|
||
+ KeyOp op = it->second;
|
||
+ if (is_read_command && (op == KeyOp::READ || op == KeyOp::READ_WRITE)) return true;
|
||
+ if (is_write_command && (op == KeyOp::WRITE || op == KeyOp::READ_WRITE)) return true;
|
||
+ }
|
||
+ /* Fall through to glob scan only for patterns with wildcards — typically empty */
|
||
for (auto& [elem, op] : keys.key_globs) {
|
||
if (Matches(elem, target)) {
|
||
if (is_read_command && (op == KeyOp::READ || op == KeyOp::READ_WRITE)) {
|
||
return true;
|
||
}
|
||
if (is_write_command && (op == KeyOp::WRITE || op == KeyOp::READ_WRITE)) {
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
return false;
|
||
};
|
||
|
||
/* Build logic (ACL SETUSER ~pattern parsing):
|
||
* - If pattern contains no glob chars (* ? [): insert into exact_keys for O(1) lookup
|
||
* - If pattern contains glob chars: append to key_globs for Matches() scan
|
||
* Reduces the common case (exact-key ACLs) from O(K×G) to O(K).
|
||
*/
|