[dovecot-cvs] dovecot/src/lib-index mailbox-list-index-private.h, 1.5, 1.6 mailbox-list-index-sync.c, 1.9, 1.10 mailbox-list-index.c, 1.8, 1.9

tss at dovecot.org tss at dovecot.org
Fri Mar 16 01:30:37 EET 2007


Update of /var/lib/cvs/dovecot/src/lib-index
In directory talvi:/tmp/cvs-serv31639

Modified Files:
	mailbox-list-index-private.h mailbox-list-index-sync.c 
	mailbox-list-index.c 
Log Message:
More desyncing fixes



Index: mailbox-list-index-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mailbox-list-index-private.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- mailbox-list-index-private.h	15 Mar 2007 13:34:49 -0000	1.5
+++ mailbox-list-index-private.h	15 Mar 2007 23:30:35 -0000	1.6
@@ -29,6 +29,8 @@
 	/* If non-zero, contains a pointer to updated directory list.
 	   Stored using mail_index_uint32_to_offset(). */
 	uint32_t next_offset;
+	/* Bytes used by this record, including mailbox names. */
+	uint32_t dir_size;
 
 	uint32_t count;
 	/* The records are sorted by their name_hash */

Index: mailbox-list-index-sync.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mailbox-list-index-sync.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- mailbox-list-index-sync.c	15 Mar 2007 17:02:07 -0000	1.9
+++ mailbox-list-index-sync.c	15 Mar 2007 23:30:35 -0000	1.10
@@ -493,7 +493,7 @@
 	struct mailbox_list_record *new_recs;
 	struct mailbox_list_sync_record *sync_recs;
 	unsigned int src, dest, orig, count, nondeleted_count;
-	unsigned int name_space_needed, deleted_space;
+	unsigned int space_needed, deleted_space;
 	uint32_t base_offset, name_pos, size;
 	void *base;
 
@@ -502,15 +502,14 @@
 
 	/* count how much space we need and how much we wasted for deleted
 	   records */
-	nondeleted_count = 0; name_space_needed = 0; deleted_space = 0;
+	nondeleted_count = 0; space_needed = 0; deleted_space = 0;
 	sync_recs = array_get_modifiable(&sync_dir->records, &count);
 	for (src = 0; src < count; src++) {
 		if (sync_recs[src].seen || partial) {
 			nondeleted_count++;
 			if (sync_recs[src].created) {
 				/* new record */
-				name_space_needed +=
-					strlen(sync_recs[src].name) + 1;
+				space_needed += strlen(sync_recs[src].name) + 1;
 			}
 		} else {
 			deleted_space += sizeof(*new_recs) +
@@ -519,9 +518,8 @@
 	}
 
 	/* @UNSAFE */
-	name_space_needed += sizeof(*dir) +
-		nondeleted_count * sizeof(*new_recs);
-	if (mailbox_list_index_sync_alloc_space(ctx, name_space_needed,
+	space_needed += sizeof(*dir) + nondeleted_count * sizeof(*new_recs);
+	if (mailbox_list_index_sync_alloc_space(ctx, space_needed,
 						&base, &base_offset) < 0)
 		return -1;
 	/* NOTE: any pointers to the index file may have been invalidated
@@ -541,6 +539,7 @@
 
 	new_dir = base;
 	new_dir->count = nondeleted_count;
+	new_dir->dir_size = space_needed;
 
 	new_recs = MAILBOX_LIST_RECORDS_MODIFIABLE(new_dir);
 	name_pos = (const char *)(new_recs + nondeleted_count) -
@@ -587,7 +586,7 @@
 		dest++;
 	}
 	i_assert(dest == nondeleted_count);
-	i_assert(name_pos == name_space_needed);
+	i_assert(name_pos == space_needed);
 
 	if (index->mmap_disable) {
 		file_cache_write(index->file_cache, ctx->output_buf->data,

Index: mailbox-list-index.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mailbox-list-index.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- mailbox-list-index.c	15 Mar 2007 13:34:49 -0000	1.8
+++ mailbox-list-index.c	15 Mar 2007 23:30:35 -0000	1.9
@@ -186,6 +186,21 @@
 	return 1;
 }
 
+static int mailbox_list_index_map_area(struct mailbox_list_index *index,
+				       uoff_t offset, size_t size)
+{
+	if (offset < index->mmap_size && size <= index->mmap_size - offset)
+		return 1;
+
+	if (mailbox_list_index_map(index) <= 0)
+		return -1;
+
+	if (offset < index->mmap_size && size <= index->mmap_size - offset)
+		return 1;
+	/* outside the file */
+	return 0;
+}
+
 static void
 mailbox_list_index_init_header(struct mailbox_list_index_header *hdr,
 			       uint32_t uid_validity)
@@ -405,6 +420,7 @@
 	struct mailbox_list_index *index = view->index;
 	const struct mailbox_list_dir_record *dir;
 	uint32_t next_offset, view_sync_offset, cur_offset = *offset;
+	int ret;
 
 	i_assert(index->mmap_size > 0);
 
@@ -414,10 +430,15 @@
 		const struct mail_index_header *hdr =
 			mail_index_get_header(view->mail_view);
 		view_sync_offset = hdr->sync_size;
+		i_assert(*offset < view_sync_offset);
 	}
 
 	do {
-		if (cur_offset >= index->mmap_size - sizeof(*dir)) {
+		ret = mailbox_list_index_map_area(index, cur_offset,
+						  sizeof(*dir));
+		if (ret <= 0) {
+			if (ret < 0)
+				return -1;
 			return mailbox_list_index_set_corrupted(index,
 				"dir_offset points outside file");
 		}
@@ -432,6 +453,11 @@
 			return mailbox_list_index_set_corrupted(index,
 				"next_offset points backwards");
 		}
+		if (dir->dir_size < sizeof(*dir) +
+		    dir->count * sizeof(struct mailbox_list_record)) {
+			return mailbox_list_index_set_corrupted(index,
+				"dir_size is smaller than record count");
+		}
 		if (next_offset >= view_sync_offset) {
 			/* the list index has been changed since the mail
 			   view's last sync. don't show the changes. */
@@ -440,14 +466,21 @@
 		cur_offset = next_offset;
 	} while (cur_offset != 0);
 
-	cur_offset = (const char *)dir - (const char *)index->const_mmap_base;
-	if (dir->count > INT_MAX/sizeof(struct mailbox_list_record) ||
-	    dir->count * sizeof(struct mailbox_list_record) >
-	    index->mmap_size - cur_offset) {
+	if (dir->count > INT_MAX/sizeof(struct mailbox_list_record)) {
 		mailbox_list_index_set_corrupted(index, "dir count too large");
 		return -1;
 	}
 
+	cur_offset = (const char *)dir - (const char *)index->const_mmap_base;
+
+	ret = mailbox_list_index_map_area(index, cur_offset, dir->dir_size);
+	if (ret <= 0) {
+		if (ret < 0)
+			return -1;
+		return mailbox_list_index_set_corrupted(index,
+			"dir points outside file");
+	}
+
 	*offset = cur_offset;
 	*dir_r = dir;
 	return 0;
@@ -482,6 +515,23 @@
 	return 1;
 }
 
+static bool
+mailbox_list_index_offset_exists(struct mailbox_list_index_view *view,
+				 uint32_t offset)
+{
+	const struct mail_index_header *hdr;
+
+	if (view->index->mmap_size <= sizeof(*view->index->hdr))
+		return FALSE;
+
+	if (view->mail_view == NULL)
+		return TRUE;
+	else {
+		hdr = mail_index_get_header(view->mail_view);
+		return hdr->sync_size > offset;
+	}
+}
+
 static int
 mailbox_list_index_lookup_rec(struct mailbox_list_index_view *view,
 			      uint32_t dir_offset, const char *name,
@@ -492,8 +542,8 @@
 	const char *p, *hier_name;
 	int ret;
 
-	if ((dir_offset == index->mmap_size || index->mmap_size == 0) &&
-	    dir_offset == sizeof(*index->hdr)) {
+	if (dir_offset == sizeof(*index->hdr) &&
+	    !mailbox_list_index_offset_exists(view, dir_offset)) {
 		/* root doesn't exist in the file yet */
 		return 0;
 	}
@@ -517,6 +567,10 @@
 	dir_offset = mail_index_offset_to_uint32((*rec_r)->dir_offset);
 	if (dir_offset == 0)
 		return 0;
+	if (!mailbox_list_index_offset_exists(view, dir_offset)) {
+		/* child isn't visible yet */
+		return 0;
+	}
 
 	return mailbox_list_index_lookup_rec(view, dir_offset, p + 1, rec_r);
 }
@@ -604,7 +658,10 @@
 				mail_index_offset_to_uint32(rec->dir_offset);
 		}
 	}
-	if (!ctx->failed && offset != 0) {
+
+	if (!mailbox_list_index_offset_exists(view, offset)) {
+		/* root doesn't exist / offset isn't visible */
+	} else if (!ctx->failed && offset != 0) {
 		if (mailbox_list_index_get_dir(view, &offset,
 					       &ctx->cur.dir) < 0)
 			ctx->failed = TRUE;
@@ -668,6 +725,12 @@
 	t_pop();
 
 	dir_offset = mail_index_offset_to_uint32(recs->dir_offset);
+	if (dir_offset != 0 &&
+	    !mailbox_list_index_offset_exists(ctx->view, dir_offset)) {
+		/* child isn't visible yet */
+		dir_offset = 0;
+	}
+
 	if (dir_offset != 0 && array_count(&ctx->path) < ctx->recurse_level) {
 		/* recurse into children */
 		array_append(&ctx->path, &ctx->cur, 1);



More information about the dovecot-cvs mailing list