]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
mbox: Fixed crash/corruption in some situations when the first mail was expunged.
authorTimo Sirainen <tss@iki.fi>
Wed, 6 May 2015 21:01:08 +0000 (00:01 +0300)
committerTimo Sirainen <tss@iki.fi>
Wed, 6 May 2015 21:01:08 +0000 (00:01 +0300)
This could be reproduced with default mbox settings, IMAP session that does
 - STORE 1 +FLAGS \DELETED
 - EXPUNGE

With mbox containing:

===
From root@example.com  Tue Jan 13 10:18:16 2015

a

From root@example.com  Tue Jan 13 10:18:20 2015

a

===

src/lib-storage/index/mbox/mbox-sync.c

index 6eb60be2641934569abc28524a5105f0a7d9e33e..cf99716f10c1c0e60075952769f0fc24d2f3e978 100644 (file)
@@ -640,7 +640,7 @@ static void mbox_sync_handle_expunge(struct mbox_sync_mail_context *mail_ctx)
 static int mbox_sync_handle_header(struct mbox_sync_mail_context *mail_ctx)
 {
        struct mbox_sync_context *sync_ctx = mail_ctx->sync_ctx;
-       uoff_t orig_from_offset;
+       uoff_t orig_from_offset, postlf_from_offset = (uoff_t)-1;
        off_t move_diff;
        int ret;
 
@@ -657,6 +657,7 @@ static int mbox_sync_handle_header(struct mbox_sync_mail_context *mail_ctx)
                        if (sync_ctx->first_mail_crlf_expunged)
                                mail_ctx->mail.from_offset++;
                }
+               postlf_from_offset = mail_ctx->mail.from_offset;
 
                /* read the From-line before rewriting overwrites it */
                if (mbox_read_from_line(mail_ctx) < 0)
@@ -710,10 +711,16 @@ static int mbox_sync_handle_header(struct mbox_sync_mail_context *mail_ctx)
                        /* create dummy message to describe the expunged data */
                        struct mbox_sync_mail mail;
 
+                       /* if this is going to be the first mail, increase the
+                          from_offset to point to the beginning of the
+                          From-line, because the previous [CR]LF is already
+                          covered by expunged_space. */
+                       i_assert(postlf_from_offset != (uoff_t)-1);
+                       mail_ctx->mail.from_offset = postlf_from_offset;
+
                        memset(&mail, 0, sizeof(mail));
                        mail.expunged = TRUE;
                        mail.offset = mail.from_offset =
-                               (sync_ctx->dest_first_mail ? 1 : 0) +
                                mail_ctx->mail.from_offset -
                                sync_ctx->expunged_space;
                        mail.space = sync_ctx->expunged_space;