]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
imapc: Don't process untagged replies in mailbox that isn't fully selected yet
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Thu, 9 Feb 2023 14:12:35 +0000 (16:12 +0200)
committerMarkus Valentin <markus.valentin@open-xchange.com>
Mon, 13 Feb 2023 11:39:34 +0000 (12:39 +0100)
For example if the communication was:

C: a SELECT box1
...
C: b SELECT box2
S: * 1 EXPUNGE
S: * 1 EXISTS
S: * OK [UIDVALIDITY 1675948459] UIDs valid
S: ...
S: b OK

The expunge was intended for box1, not box2. This caused:
Warning: imapc(...): Mailbox '...' state corrupted: EXPUNGE received for empty mailbox - reconnecting

Fixed this by ignoring untagged EXPUNGE, FETCH, SEARCH and ESEARCH replies
when the UIDVALIDITY reply hasn't been yet received for a mailbox.

src/lib-storage/index/imapc/imapc-mailbox.c
src/lib-storage/index/imapc/imapc-storage.h

index ff915d96118933bbc2e3308c645032fd01345929..5e3e55a3a8f821bcfd18fbad995b9aa5165eaa21 100644 (file)
@@ -696,6 +696,11 @@ static void imapc_untagged_fetch(const struct imapc_untagged_reply *reply,
 
        if (mbox == NULL || reply->num == 0 || !imap_arg_get_list(reply->args, &list))
                return;
+       if (!IMAPC_MAILBOX_IS_FULLY_SELECTED(mbox)) {
+               /* SELECTing another mailbox - this FETCH is still for the
+                  previous selected mailbox. */
+               return;
+       }
 
        struct imapc_untagged_fetch_ctx *ctx =
                imapc_untagged_fetch_ctx_create();
@@ -737,6 +742,11 @@ static void imapc_untagged_expunge(const struct imapc_untagged_reply *reply,
        if (mbox == NULL || rseq == 0 ||
            IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_NO_MSN_UPDATES))
                return;
+       if (!IMAPC_MAILBOX_IS_FULLY_SELECTED(mbox)) {
+               /* SELECTing another mailbox - this EXPUNGE is still for the
+                  previous selected mailbox. */
+               return;
+       }
 
        mbox->prev_skipped_rseq = 0;
        mbox->prev_skipped_uid = 0;
@@ -819,8 +829,14 @@ imapc_untagged_esearch_gmail_pop3(const struct imap_arg *args,
 static void imapc_untagged_search(const struct imapc_untagged_reply *reply,
                                  struct imapc_mailbox *mbox)
 {
-       if (mbox != NULL)
-               imapc_search_reply_search(reply->args, mbox);
+       if (mbox == NULL)
+               return;
+       if (!IMAPC_MAILBOX_IS_FULLY_SELECTED(mbox)) {
+               /* SELECTing another mailbox - this SEARCH is still for the
+                  previous selected mailbox. */
+               return;
+       }
+       imapc_search_reply_search(reply->args, mbox);
 }
 
 static void imapc_untagged_esearch(const struct imapc_untagged_reply *reply,
@@ -831,6 +847,11 @@ static void imapc_untagged_esearch(const struct imapc_untagged_reply *reply,
 
        if (mbox == NULL || !imap_arg_get_list(reply->args, &tag_list))
                return;
+       if (!IMAPC_MAILBOX_IS_FULLY_SELECTED(mbox)) {
+               /* SELECTing another mailbox - this ESEARCH is still for the
+                  previous selected mailbox. */
+               return;
+       }
 
        /* ESEARCH begins with (TAG <tag>) */
        if (!imap_arg_atom_equals(&tag_list[0], "TAG") ||
index e02c5687e46a5c51f9c61db4a125a85d7feb8371..6624a0d1bf5b38b6a755bf53e14b0f10a2c5c387 100644 (file)
@@ -39,6 +39,12 @@ struct imapc_mailbox_event_callback {
 #define IMAPC_BOX_HAS_FEATURE(mbox, feature) \
        (((mbox)->storage->set->parsed_features & feature) != 0)
 
+/* Returns TRUE if we can assume from now on that untagged EXPUNGE, FETCH, etc.
+   replies belong to this mailbox instead of to the previously selected
+   mailbox. */
+#define IMAPC_MAILBOX_IS_FULLY_SELECTED(mbox) \
+       ((mbox)->sync_uid_validity != 0)
+
 struct imapc_namespace {
        const char *prefix;
        char separator;