dovecot: If hdr.messages_count is too large, fix it with fsck in...

dovecot at dovecot.org dovecot at dovecot.org
Sat Sep 15 10:05:59 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/0a90044b42c9
changeset: 6374:0a90044b42c9
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Sep 15 09:21:47 2007 +0300
description:
If hdr.messages_count is too large, fix it with fsck instead of treating the
index completely corrupted.

diffstat:

1 file changed, 14 insertions(+), 9 deletions(-)
src/lib-index/mail-index-map.c |   23 ++++++++++++++---------

diffs (88 lines):

diff -r 06818dd6a952 -r 0a90044b42c9 src/lib-index/mail-index-map.c
--- a/src/lib-index/mail-index-map.c	Sat Sep 15 08:55:57 2007 +0300
+++ b/src/lib-index/mail-index-map.c	Sat Sep 15 09:21:47 2007 +0300
@@ -290,6 +290,8 @@ int mail_index_map_check_header(struct m
 		return 0;
 	if (hdr->next_uid == 0)
 		return 0;
+	if (hdr->messages_count > map->rec_map->records_count)
+		return 0;
 
 	if (hdr->seen_messages_count > hdr->messages_count ||
 	    hdr->deleted_messages_count > hdr->messages_count)
@@ -335,7 +337,6 @@ static int mail_index_mmap(struct mail_i
 	struct mail_index *index = map->index;
 	struct mail_index_record_map *rec_map = map->rec_map;
 	const struct mail_index_header *hdr;
-	unsigned int records_count;
 
 	i_assert(rec_map->mmap_base == NULL);
 
@@ -381,21 +382,24 @@ static int mail_index_mmap(struct mail_i
 	rec_map->mmap_used_size = hdr->header_size +
 		hdr->messages_count * hdr->record_size;
 
-	if (rec_map->mmap_used_size > rec_map->mmap_size) {
-		records_count = (rec_map->mmap_size - hdr->header_size) /
+	if (rec_map->mmap_used_size <= rec_map->mmap_size)
+		rec_map->records_count = hdr->messages_count;
+	else {
+		rec_map->records_count =
+			(rec_map->mmap_size - hdr->header_size) /
 			hdr->record_size;
+		rec_map->mmap_used_size = hdr->header_size +
+			rec_map->records_count * hdr->record_size;
 		mail_index_set_error(index, "Corrupted index file %s: "
 				     "messages_count too large (%u > %u)",
 				     index->filepath, hdr->messages_count,
-				     records_count);
-		return 0;
+				     rec_map->records_count);
 	}
 
 	mail_index_map_copy_hdr(map, hdr);
 
 	map->hdr_base = rec_map->mmap_base;
 	rec_map->records = PTR_OFFSET(rec_map->mmap_base, map->hdr.header_size);
-	rec_map->records_count = map->hdr.messages_count;
 	return 1;
 }
 
@@ -434,7 +438,7 @@ mail_index_try_read_map(struct mail_inde
 	void *data = NULL;
 	ssize_t ret;
 	size_t pos, records_size, initial_buf_pos = 0;
-	unsigned int records_count, extra;
+	unsigned int records_count = 0, extra;
 
 	i_assert(map->rec_map->mmap_base == NULL);
 
@@ -476,17 +480,18 @@ mail_index_try_read_map(struct mail_inde
 	if (ret > 0) {
 		/* header read, read the records now. */
 		records_size = (size_t)hdr->messages_count * hdr->record_size;
+		records_count = hdr->messages_count;
 
 		if (file_size - hdr->header_size < records_size ||
 		    (hdr->record_size != 0 &&
 		     records_size / hdr->record_size != hdr->messages_count)) {
 			records_count = (file_size - hdr->header_size) /
 				hdr->record_size;
+			records_size = (size_t)records_count * hdr->record_size;
 			mail_index_set_error(index, "Corrupted index file %s: "
 				"messages_count too large (%u > %u)",
 				index->filepath, hdr->messages_count,
 				records_count);
-			return 0;
 		}
 
 		if (map->rec_map->buffer == NULL) {
@@ -531,7 +536,7 @@ mail_index_try_read_map(struct mail_inde
 
 	map->rec_map->records =
 		buffer_get_modifiable_data(map->rec_map->buffer, NULL);
-	map->rec_map->records_count = hdr->messages_count;
+	map->rec_map->records_count = records_count;
 
 	mail_index_map_copy_hdr(map, hdr);
 	map->hdr_base = map->hdr_copy_buf->data;


More information about the dovecot-cvs mailing list