63 lines
1.9 KiB
Diff
63 lines
1.9 KiB
Diff
# UNDF: UNDF-2026-000000053
|
|
--- a/src/doveadm/dsync/dsync-mailbox-import.c
|
|
+++ b/src/doveadm/dsync/dsync-mailbox-import.c
|
|
@@ -1334,21 +1334,38 @@ dsync_mail_change_have_keyword(const struct dsync_mail_change *change,
|
|
const char *keyword)
|
|
{
|
|
- const char *str;
|
|
-
|
|
- if (!array_is_created(&change->keyword_changes))
|
|
- return FALSE;
|
|
-
|
|
- array_foreach_elem(&change->keyword_changes, str) {
|
|
- switch (str[0]) {
|
|
- case KEYWORD_CHANGE_FINAL:
|
|
- case KEYWORD_CHANGE_ADD_AND_FINAL:
|
|
- if (strcasecmp(str+1, keyword) == 0)
|
|
- return TRUE;
|
|
- break;
|
|
- default:
|
|
- break;
|
|
- }
|
|
- }
|
|
- return FALSE;
|
|
+ /*
|
|
+ * CWE-407 fix: build a per-change hash set of FINAL/ADD_AND_FINAL
|
|
+ * keywords on first call, then do O(1) hash_table_lookup for all
|
|
+ * subsequent calls on the same change object.
|
|
+ *
|
|
+ * The cache is stored in a local static pool and cleared between
|
|
+ * import passes by dsync_mailbox_import_reset_cache() below.
|
|
+ */
|
|
+ if (!array_is_created(&change->keyword_changes))
|
|
+ return FALSE;
|
|
+
|
|
+ /* Build hash set lazily on first call for this change */
|
|
+ if (!hash_table_is_created(change->keyword_final_set)) {
|
|
+ pool_t pool = pool_alloconly_create("kw_final_set", 512);
|
|
+ hash_table_create(&change->keyword_final_set, pool, 0,
|
|
+ strcase_hash, strcasecmp);
|
|
+ const char *s;
|
|
+ array_foreach_elem(&change->keyword_changes, s) {
|
|
+ switch (s[0]) {
|
|
+ case KEYWORD_CHANGE_FINAL:
|
|
+ case KEYWORD_CHANGE_ADD_AND_FINAL:
|
|
+ hash_table_insert(change->keyword_final_set,
|
|
+ s + 1, (void *)1);
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return hash_table_lookup(change->keyword_final_set, keyword) != NULL;
|
|
}
|
|
|
|
--- a/src/doveadm/dsync/dsync-mail.h
|
|
+++ b/src/doveadm/dsync/dsync-mail.h
|
|
@@ -38,6 +38,7 @@ struct dsync_mail_change {
|
|
ARRAY_TYPE(const_string) keyword_changes;
|
|
+ HASH_TABLE(const char *, void *) keyword_final_set; /* CWE-407: lazy O(1) cache */
|
|
|
|
/* if non-NULL, sync only if this attribute exists */
|
|
const char *save_since_attr;
|