]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-index: Fix potential assert-crash when refreshing index without any views
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Mon, 27 Jan 2020 20:52:51 +0000 (22:52 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Fri, 31 Jan 2020 12:36:10 +0000 (12:36 +0000)
This is similar to the previous fix. If there are no references to the log
file head, refreshing the index will result in assert-crash.

This seems to have happened in some very rare situations. Mainly found it
via the unit test though.

Fixes:
Panic: file mail-transaction-log.c: line 25 (mail_transaction_log_set_head): assertion failed: (log->files != NULL)

src/lib-index/mail-transaction-log.c
src/lib-index/test-mail-index.c

index 5a9cee1623be5a9a22e72cb7b4a5e95153bb6e45..1133a83bb018017e7a86dcba1ad99137f642e884 100644 (file)
@@ -368,9 +368,10 @@ mail_transaction_log_refresh(struct mail_transaction_log *log, bool nfs_flush,
 
        i_assert(!file->locked);
 
-       if (--log->head->refcount == 0)
-               mail_transaction_logs_clean(log);
+       struct mail_transaction_log_file *old_head = log->head;
        mail_transaction_log_set_head(log, file);
+       if (--old_head->refcount == 0)
+               mail_transaction_logs_clean(log);
        *reason_r = "Log reopened";
        return 0;
 }
index c18f42b5f792028409c43ae43b797e7dbaab52e9..f54ea39ec9213911c6dfe259c129ce0bd505a0d3 100644 (file)
@@ -8,12 +8,15 @@
 
 static void test_mail_index_rotate(void)
 {
-       struct mail_index *index;
+       struct mail_index *index, *index2;
        struct mail_index_view *view;
        struct mail_index_transaction *trans;
+       struct mail_transaction_log_file *file;
+       const char *reason;
 
        test_begin("mail index rotate");
        index = test_mail_index_init();
+       index2 = test_mail_index_open();
        view = mail_index_view_open(index);
 
        /* First rotation of the index. The view will point to the old index. */
@@ -27,8 +30,13 @@ static void test_mail_index_rotate(void)
        mail_index_reset(trans);
        test_assert(mail_index_transaction_commit(&trans) == 0);
 
+       /* The 2nd index's log head also doesn't have any extra references.
+          Check that it doesn't crash. */
+       test_assert(mail_transaction_log_find_file(index2->log, 3, FALSE, &file, &reason) == 0);
+
        mail_index_view_close(&view);
        test_mail_index_deinit(&index);
+       test_mail_index_deinit(&index2);
        test_end();
 }