dovecot-2.2: lib-index: Assert-crashfix on some rare situations.

dovecot at dovecot.org dovecot at dovecot.org
Wed Apr 10 16:51:23 EEST 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/286fa7f9538c
changeset: 16265:286fa7f9538c
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Apr 10 16:50:34 2013 +0300
description:
lib-index: Assert-crashfix on some rare situations.
mail_index_modseq_get_next_log_offset() might have returned e.g. (seq=4,
offset=40) to point to the beginning of a next file. The view itself could
still have been pointing to seq=3 end of file. Now calling
mail_transaction_log_view_set() with these two positions (that are basically
the same) should result in an empty view instead of assert crash.

diffstat:

 src/lib-index/mail-transaction-log-view.c |  34 +++++++++++++++++++-----------
 1 files changed, 21 insertions(+), 13 deletions(-)

diffs (88 lines):

diff -r 08602cf498ea -r 286fa7f9538c src/lib-index/mail-transaction-log-view.c
--- a/src/lib-index/mail-transaction-log-view.c	Wed Apr 10 14:52:17 2013 +0300
+++ b/src/lib-index/mail-transaction-log-view.c	Wed Apr 10 16:50:34 2013 +0300
@@ -63,14 +63,12 @@
 				  uint32_t max_file_seq, uoff_t max_file_offset,
 				  bool *reset_r)
 {
-	struct mail_transaction_log_file *file, *const *files, *tail;
+	struct mail_transaction_log_file *file, *const *files;
 	uoff_t start_offset, end_offset;
 	unsigned int i;
 	uint32_t seq;
 	int ret;
 
-	i_assert(min_file_seq <= max_file_seq);
-
 	*reset_r = FALSE;
 
 	if (view->log == NULL) {
@@ -79,28 +77,35 @@
 		return -1;
 	}
 
-	tail = view->log->files;
 	if (min_file_seq == 0) {
 		/* index file doesn't exist yet. this transaction log should
 		   start from the beginning */
-		if (tail->hdr.prev_file_seq != 0) {
+		if (view->log->files->hdr.prev_file_seq != 0) {
 			/* but it doesn't */
 			return 0;
 		}
 
-		min_file_seq = tail->hdr.file_seq;
+		min_file_seq = view->log->files->hdr.file_seq;
 		min_file_offset = 0;
 
 		if (max_file_seq == 0) {
 			max_file_seq = min_file_seq;
 			max_file_offset = min_file_offset;
 		}
-	} 
+	}
 
-	if (min_file_seq == tail->hdr.prev_file_seq &&
-	    min_file_offset == tail->hdr.prev_file_offset) {
-		/* we can skip this */
-		min_file_seq = tail->hdr.file_seq;
+	for (file = view->log->files; file != NULL; file = file->next) {
+		if (file->hdr.prev_file_seq == min_file_seq)
+			break;
+	}
+	if (file != NULL && min_file_offset == file->hdr.prev_file_offset) {
+		/* we can skip to the next file. we've delayed checking for
+		   min_file_seq <= max_file_seq until now, because it's not
+		   really an error to specify the same position twice (even if
+		   in "wrong" order) */
+		i_assert(min_file_seq <= max_file_seq ||
+			 file->hdr.file_seq <= max_file_seq);
+		min_file_seq = file->hdr.file_seq;
 		min_file_offset = 0;
 
 		if (min_file_seq > max_file_seq) {
@@ -108,6 +113,8 @@
 			max_file_seq = min_file_seq;
 			max_file_offset = min_file_offset;
 		}
+	} else {
+		i_assert(min_file_seq <= max_file_seq);
 	}
 
 	if (min_file_seq == max_file_seq && min_file_offset > max_file_offset) {
@@ -119,12 +126,13 @@
 		return -1;
 	}
 
-	if (min_file_offset > 0 && min_file_offset < tail->hdr.hdr_size) {
+	if (min_file_offset > 0 && file != NULL &&
+	    min_file_offset < file->hdr.hdr_size) {
 		/* log file offset is probably corrupted in the index file. */
 		mail_transaction_log_view_set_corrupted(view,
 			"file_seq=%u, min_file_offset (%"PRIuUOFF_T
 			") < hdr_size (%u)",
-			min_file_seq, min_file_offset, tail->hdr.hdr_size);
+			min_file_seq, min_file_offset, file->hdr.hdr_size);
 		return -1;
 	}
 


More information about the dovecot-cvs mailing list