dovecot-2.2: zlib: Fixed copying causing cache corruption when z...
dovecot at dovecot.org
dovecot at dovecot.org
Fri Nov 27 12:57:30 UTC 2015
details: http://hg.dovecot.org/dovecot-2.2/rev/574c1e5b3d90
changeset: 19427:574c1e5b3d90
user: Timo Sirainen <tss at iki.fi>
date: Fri Nov 27 14:57:03 2015 +0200
description:
zlib: Fixed copying causing cache corruption when zlib_save wasn't set.
dovecot.index.cache entries were broken/missing if:
- The zlib plugin is enabled;
- The zlib_save/zlib_save_level options are NOT enabled;
- The source message being copied is compressed;
- The mail_log plugin is logging "copy" events;
- The mail_log_fields setting includes at least one message header;
- The destination mailbox folder has an index file that is recording the
logged headers;
- The source mailbox folder does NOT have an index file recording the
logged headers.
Found by Robert L Mathews.
diffstat:
src/plugins/zlib/zlib-plugin.c | 40 +++++++++++++++++++++++++---------------
1 files changed, 25 insertions(+), 15 deletions(-)
diffs (99 lines):
diff -r 2ddbdf05b19b -r 574c1e5b3d90 src/plugins/zlib/zlib-plugin.c
--- a/src/plugins/zlib/zlib-plugin.c Fri Nov 27 14:42:43 2015 +0200
+++ b/src/plugins/zlib/zlib-plugin.c Fri Nov 27 14:57:03 2015 +0200
@@ -26,6 +26,11 @@
#define MAX_INBUF_SIZE (1024*1024)
#define ZLIB_MAIL_CACHE_EXPIRE_MSECS (60*1000)
+struct zlib_mail {
+ union mail_module_context module_ctx;
+ bool verifying_save;
+};
+
struct zlib_transaction_context {
union mailbox_transaction_module_context module_ctx;
@@ -112,16 +117,15 @@
struct zlib_user *zuser = ZLIB_USER_CONTEXT(_mail->box->storage->user);
struct zlib_mail_cache *cache = &zuser->cache;
struct mail_private *mail = (struct mail_private *)_mail;
- union mail_module_context *zmail = ZLIB_MAIL_CONTEXT(mail);
+ struct zlib_mail *zmail = ZLIB_MAIL_CONTEXT(mail);
struct istream *input;
const struct compression_handler *handler;
- /* don't uncompress input when we are reading a mail that we're just
- in the middle of saving, and we didn't do the compression ourself.
- in such situation we're probably checking if the user-given input
- looks compressed */
- if (_mail->saving && zuser->save_handler == NULL)
- return zmail->super.istream_opened(_mail, stream);
+ if (zmail->verifying_save) {
+ /* zlib_mail_save_finish() is verifying that the user-given
+ input doesn't look compressed. */
+ return zmail->module_ctx.super.istream_opened(_mail, stream);
+ }
if (cache->uid == _mail->uid && cache->box == _mail->box) {
/* use the cached stream. when doing partial reads it should
@@ -129,7 +133,7 @@
i_stream_unref(stream);
i_stream_seek(cache->input, 0);
*stream = i_stream_create_limit(cache->input, (uoff_t)-1);
- return zmail->super.istream_opened(_mail, stream);
+ return zmail->module_ctx.super.istream_opened(_mail, stream);
}
handler = compression_detect_handler(*stream);
@@ -147,7 +151,7 @@
*stream = zlib_mail_cache_open(zuser, _mail, *stream);
}
- return zmail->super.istream_opened(_mail, stream);
+ return zmail->module_ctx.super.istream_opened(_mail, stream);
}
static void zlib_mail_allocated(struct mail *_mail)
@@ -155,17 +159,17 @@
struct zlib_transaction_context *zt = ZLIB_CONTEXT(_mail->transaction);
struct mail_private *mail = (struct mail_private *)_mail;
struct mail_vfuncs *v = mail->vlast;
- union mail_module_context *zmail;
+ struct zlib_mail *zmail;
if (zt == NULL)
return;
- zmail = p_new(mail->pool, union mail_module_context, 1);
- zmail->super = *v;
- mail->vlast = &zmail->super;
+ zmail = p_new(mail->pool, struct zlib_mail, 1);
+ zmail->module_ctx.super = *v;
+ mail->vlast = &zmail->module_ctx.super;
v->istream_opened = zlib_istream_opened;
- MODULE_CONTEXT_SET_SELF(mail, zlib_mail_module, zmail);
+ MODULE_CONTEXT_SET(mail, zlib_mail_module, zmail);
}
static struct mailbox_transaction_context *
@@ -235,12 +239,18 @@
{
struct mailbox *box = ctx->transaction->box;
union mailbox_module_context *zbox = ZLIB_CONTEXT(box);
+ struct mail_private *mail = (struct mail_private *)ctx->dest_mail;
+ struct zlib_mail *zmail = ZLIB_MAIL_CONTEXT(mail);
struct istream *input;
+ int ret;
if (zbox->super.save_finish(ctx) < 0)
return -1;
- if (mail_get_stream(ctx->dest_mail, NULL, NULL, &input) < 0)
+ zmail->verifying_save = TRUE;
+ ret = mail_get_stream(ctx->dest_mail, NULL, NULL, &input);
+ zmail->verifying_save = FALSE;
+ if (ret < 0)
return -1;
if (compression_detect_handler(input) != NULL) {
More information about the dovecot-cvs
mailing list