changeset 2917:e657c7874962 HEAD

Crashfixes for reading corrupted cache files.
author Timo Sirainen <tss@iki.fi>
date Mon, 29 Nov 2004 14:30:27 +0200
parents d1780331ad04
children 7039fc53b4c8
files src/lib-index/mail-cache-lookup.c src/lib-index/mail-cache-private.h src/lib-index/mail-cache-transaction.c
diffstat 3 files changed, 24 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-index/mail-cache-lookup.c	Mon Nov 29 14:21:24 2004 +0200
+++ b/src/lib-index/mail-cache-lookup.c	Mon Nov 29 14:30:27 2004 +0200
@@ -9,40 +9,43 @@
 
 #define CACHE_PREFETCH 1024
 
-const struct mail_cache_record *
-mail_cache_get_record(struct mail_cache *cache, uint32_t offset)
+int mail_cache_get_record(struct mail_cache *cache, uint32_t offset,
+			  const struct mail_cache_record **rec_r)
 {
 	const struct mail_cache_record *cache_rec;
 
+	*rec_r = NULL;
 	if (offset == 0)
-		return NULL;
+		return 0;
 
 	if (mail_cache_map(cache, offset,
 			   sizeof(*cache_rec) + CACHE_PREFETCH) < 0)
-		return NULL;
+		return -1;
 
 	if (offset + sizeof(*cache_rec) > cache->mmap_length) {
 		mail_cache_set_corrupted(cache, "record points outside file");
-		return NULL;
+		return -1;
 	}
 	cache_rec = CACHE_RECORD(cache, offset);
 
 	if (cache_rec->size < sizeof(*cache_rec)) {
 		mail_cache_set_corrupted(cache, "invalid record size");
-		return NULL;
+		return -1;
 	}
 	if (cache_rec->size > CACHE_PREFETCH) {
 		if (mail_cache_map(cache, offset, cache_rec->size) < 0)
-			return NULL;
+			return -1;
 		cache_rec = CACHE_RECORD(cache, offset);
 	}
 
 	if (cache_rec->size > cache->mmap_length ||
 	    offset + cache_rec->size > cache->mmap_length) {
 		mail_cache_set_corrupted(cache, "record points outside file");
-		return NULL;
+		return -1;
 	}
-	return cache_rec;
+
+	*rec_r = cache_rec;
+	return 0;
 }
 
 static int
@@ -94,7 +97,8 @@
 	unsigned int field;
 	int ret;
 
-	cache_rec = mail_cache_get_record(view->cache, *offset);
+	if (mail_cache_get_record(view->cache, *offset, &cache_rec) < 0)
+		return -1;
 	if (cache_rec == NULL) {
 		*offset = 0;
 		return 1;
@@ -126,7 +130,9 @@
 
 			/* field reading might have re-mmaped the file and
 			   caused cache_rec to break. need to get it again. */
-			cache_rec = mail_cache_get_record(view->cache, *offset);
+			if (mail_cache_get_record(view->cache, *offset,
+						  &cache_rec) < 0)
+				return -1;
 			i_assert(cache_rec != NULL);
 		}
 
--- a/src/lib-index/mail-cache-private.h	Mon Nov 29 14:21:24 2004 +0200
+++ b/src/lib-index/mail-cache-private.h	Mon Nov 29 14:30:27 2004 +0200
@@ -178,8 +178,8 @@
 int mail_cache_header_fields_get_next_offset(struct mail_cache *cache,
 					     uint32_t *offset_r);
 
-const struct mail_cache_record *
-mail_cache_get_record(struct mail_cache *cache, uint32_t offset);
+int mail_cache_get_record(struct mail_cache *cache, uint32_t offset,
+			  const struct mail_cache_record **rec_r);
 
 int mail_cache_foreach(struct mail_cache_view *view, uint32_t seq,
 		       mail_cache_foreach_callback_t *callback, void *context);
--- a/src/lib-index/mail-cache-transaction.c	Mon Nov 29 14:21:24 2004 +0200
+++ b/src/lib-index/mail-cache-transaction.c	Mon Nov 29 14:30:27 2004 +0200
@@ -768,7 +768,8 @@
 
 	i_assert(cache->locked);
 
-	cache_rec = mail_cache_get_record(cache, offset);
+	if (mail_cache_get_record(cache, offset, &cache_rec) < 0)
+		return -1;
 	if (cache_rec == NULL)
 		return 0;
 
@@ -779,8 +780,9 @@
 	   expunged. */
 	do {
 		cache->hdr_copy.deleted_space += cache_rec->size;
-		cache_rec =
-			mail_cache_get_record(cache, cache_rec->prev_offset);
+		if (mail_cache_get_record(cache, cache_rec->prev_offset,
+					  &cache_rec) < 0)
+			return -1;
 	} while (cache_rec != NULL);
 
 	cache->hdr_modified = TRUE;