changeset 6374:0a90044b42c9 HEAD

If hdr.messages_count is too large, fix it with fsck instead of treating the index completely corrupted.
author Timo Sirainen <tss@iki.fi>
date Sat, 15 Sep 2007 09:21:47 +0300
parents 06818dd6a952
children fc2f5607108d
files src/lib-index/mail-index-map.c
diffstat 1 files changed, 14 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- 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 @@
 		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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 
 	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;