java-topology/docs/tickets/dovecot-0001-dsync-keyword-linear-scan.md

2.2 KiB
Raw Blame History

dovecot-0001 — Quadratic dsync keyword matching via linear array scan

Target: Dovecot core (dovecot/core) Severity: LOW-MEDIUM CWE: CWE-407 (Algorithmic Complexity — Quadratic) Status: PATCHED (patch/dovecot-0001.patch)

Summary

dsync_mail_change_have_keyword() in doveadm/dsync/dsync-mailbox-import.c uses array_foreach_elem to linearly scan all keyword changes O(K) to find a single keyword match. It is called for every mail change record when importer->sync_keyword is set (i.e., when the user runs doveadm sync -k <keyword>). With M mail changes and K keyword-change entries per change record, the total cost is O(M × K).

For a mailbox being sync'd with M=50 000 messages and K=20 keyword changes per message, this is 1 000 000 string comparisons during the sync pass.

Location

src/doveadm/dsync/dsync-mailbox-import.c
  lines 1336-1354   dsync_mail_change_have_keyword() — O(K) array_foreach_elem
  line  1400         called inside dsync_mailbox_import_want_change()
                     which is called per mail change during import

Root Cause

change->keyword_changes is an ARRAY_TYPE(const_string) (dynamic array). dsync_mail_change_have_keyword iterates it with array_foreach_elem performing strcasecmp per element. No hash set is maintained for the keyword change list. The function is called repeatedly for the same change object when testing multiple keywords, but the scan is repeated in full each time.

Fix

When sync_keyword is set, pre-build a hash_table_t of KEYWORD_CHANGE_FINAL and KEYWORD_CHANGE_ADD_AND_FINAL keywords from change->keyword_changes before the main import loop begins, or build a per-change p_hash_table at first access.

Alternatively, since sync_keyword is a single string, sort change->keyword_changes at construction time and binary-search for the target prefix substring (O(log K) per lookup).

Complexity

  • Slow: O(M × K) — M mail changes × K keyword-change entries per change
  • Fast: O(M) — O(1) hash lookup per mail change
  • Speedup at M=50000, K=20: ~20×

Patch

See defects/dovecot/patch/dovecot-0001.patch

Unit Test

See defects/dovecot/unit/DovecotTest.java