[dovecot-cvs] dovecot/src/lib-index mail-cache-lookup.c,1.21,1.22

cras at dovecot.org cras at dovecot.org
Thu Sep 16 17:03:03 EEST 2004


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

Modified Files:
	mail-cache-lookup.c 
Log Message:
Make sure we don't get into infinite loops while reading cache.



Index: mail-cache-lookup.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-cache-lookup.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- mail-cache-lookup.c	12 Sep 2004 14:02:46 -0000	1.21
+++ mail-cache-lookup.c	16 Sep 2004 14:03:00 -0000	1.22
@@ -37,7 +37,8 @@
 		cache_rec = CACHE_RECORD(cache, offset);
 	}
 
-	if (offset + cache_rec->size > cache->mmap_length) {
+	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;
 	}
@@ -124,9 +125,9 @@
 		}
 
 		next_pos = pos + ((data_size + 3) & ~3);
-		if (next_pos > cache_rec->size) {
+		if (data_size > cache_rec->size || next_pos > cache_rec->size) {
 			mail_cache_set_corrupted(cache,
-				"Record continues outside it's allocated size");
+				"record continues outside it's allocated size");
 			return -1;
 		}
 
@@ -142,10 +143,26 @@
 	return 1;
 }
 
+static int buffer_find_offset(const buffer_t *buffer, uint32_t offset)
+{
+	const uint32_t *offsets;
+	size_t i, size;
+
+	offsets = buffer_get_data(buffer, &size);
+	size /= sizeof(*offsets);
+
+	for (i = 0; i < size; i++) {
+		if (offsets[i] == offset)
+			return TRUE;
+	}
+	return FALSE;
+}
+
 int mail_cache_foreach(struct mail_cache_view *view, uint32_t seq,
                        mail_cache_foreach_callback_t *callback, void *context)
 {
 	uint32_t offset;
+	buffer_t *offsets;
 	int ret;
 
         if (MAIL_CACHE_IS_UNUSABLE(view->cache))
@@ -161,23 +178,40 @@
 		view->cached_offset = offset;
 	}
 
-	while (offset != 0) {
+	t_push();
+	offsets = buffer_create_dynamic(pool_datastack_create(),
+					128, (size_t)-1);
+	ret = 1;
+	while (offset != 0 && ret > 0) {
+		if (buffer_find_offset(offsets, offset)) {
+			mail_cache_set_corrupted(view->cache,
+						 "record list is circular");
+			ret = -1;
+			break;
+		}
+		buffer_append(offsets, &offset, sizeof(offset));
 		ret = mail_cache_foreach_rec(view, &offset,
 					     callback, context);
-		if (ret <= 0)
-			return ret;
 	}
 
-	if (view->trans_seq1 <= seq && view->trans_seq2 >= seq &&
+	if (ret > 0 && view->trans_seq1 <= seq && view->trans_seq2 >= seq &&
 	    mail_cache_transaction_lookup(view->transaction, seq, &offset)) {
-		while (offset != 0) {
+		buffer_set_used_size(offsets, 0);
+		while (offset != 0 && ret > 0) {
+			if (buffer_find_offset(offsets, offset)) {
+				mail_cache_set_corrupted(view->cache,
+					"record list is circular");
+				ret = -1;
+				break;
+			}
+			buffer_append(offsets, &offset, sizeof(offset));
 			ret = mail_cache_foreach_rec(view, &offset,
 						     callback, context);
-			if (ret <= 0)
-				return ret;
 		}
 	}
-	return 1;
+	t_pop();
+
+	return ret;
 }
 
 static int



More information about the dovecot-cvs mailing list