changeset 48:5e9cf9565353 HEAD

More cleanups / potential overflow fixes
author Timo Sirainen <tss@iki.fi>
date Tue, 27 Aug 2002 06:36:09 +0300
parents 306c20092a96
children 6be018ca51ef
files src/lib-index/mail-index-compress.c src/lib-index/mail-index-data.c src/lib-index/mail-index-data.h src/lib-index/mail-index-update-cache.c src/lib-index/mail-index.h
diffstat 5 files changed, 95 insertions(+), 67 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-index/mail-index-compress.c	Tue Aug 27 06:33:10 2002 +0300
+++ b/src/lib-index/mail-index-compress.c	Tue Aug 27 06:36:09 2002 +0300
@@ -11,24 +11,29 @@
 
 int mail_index_compress(MailIndex *index)
 {
-	MailIndexHeader *hdr;
 	MailIndexRecord *rec, *hole_rec, *end_rec;
-	off_t fsize;
+	size_t fsize;
 
 	if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE))
 		return FALSE;
 
-	hdr = index->get_header(index);
-
-	if (hdr->first_hole_position == 0) {
+	if (index->header->first_hole_position == 0) {
 		/* we don't need to compress after all. shouldn't happen.. */
 		index->header->flags &= ~MAIL_INDEX_FLAG_CACHE_FIELDS;
 		return TRUE;
 	}
 
+	if (index->header->first_hole_position >= (off_t)index->mmap_length) {
+		index_set_error(index, "Error in index file %s: "
+				"first_hole_position points outside file",
+				index->filepath);
+		index->header->flags |= MAIL_INDEX_FLAG_REBUILD;
+		return FALSE;
+	}
+
 	/* if we get interrupted, the whole index is probably corrupted.
 	   so keep rebuild-flag on while doing this */
-	hdr->flags |= MAIL_INDEX_FLAG_REBUILD;
+	index->header->flags |= MAIL_INDEX_FLAG_REBUILD;
 	if (!mail_index_fmsync(index, sizeof(MailIndexHeader)))
 		return FALSE;
 
@@ -36,8 +41,8 @@
 	end_rec = (MailIndexRecord *) ((char *) index->mmap_base +
 				       index->mmap_length);
 	hole_rec = (MailIndexRecord *) ((char *) index->mmap_base +
-					hdr->first_hole_position);
-	rec = hole_rec + hdr->first_hole_records;
+					index->header->first_hole_position);
+	rec = hole_rec + index->header->first_hole_records;
 	while (rec < end_rec) {
 		if (rec->uid != 0) {
 			memcpy(hole_rec, rec, sizeof(MailIndexRecord));
@@ -47,8 +52,8 @@
 	}
 
 	/* truncate the file to get rid of the extra records */
-	fsize = (char *) hole_rec - (char *) index->mmap_base;
-	if (ftruncate(index->fd, fsize) == -1) {
+	fsize = (size_t) ((char *) hole_rec - (char *) index->mmap_base);
+	if (ftruncate(index->fd, (off_t)fsize) == -1) {
 		index_set_error(index, "ftruncate() failed for %s: %m",
 				index->filepath);
 		return FALSE;
@@ -67,13 +72,61 @@
 	return TRUE;
 }
 
-int mail_index_compress_data(MailIndex *index)
+static int mail_index_copy_data(MailIndex *index, int fd, const char *path)
 {
+	MailIndexDataHeader data_hdr;
 	MailIndexRecord *rec;
-	MailIndexDataHeader data_hdr;
 	unsigned char *mmap_data;
 	size_t mmap_data_size;
 	off_t offset;
+
+	mmap_data = mail_index_data_get_mmaped(index->data, &mmap_data_size);
+	if (mmap_data == NULL)
+		return FALSE;
+
+	/* write data header */
+	memset(&data_hdr, 0, sizeof(data_hdr));
+	data_hdr.indexid = index->indexid;
+	if (write_full(fd, &data_hdr, sizeof(data_hdr)) < 0) {
+		index_set_error(index, "Error writing to temp index data "
+				"%s: %m", path);
+		return FALSE;
+	}
+
+	/* no we'll begin the actual moving. keep rebuild-flag on
+	   while doing it. */
+	index->header->flags |= MAIL_INDEX_FLAG_REBUILD;
+	if (!mail_index_fmsync(index, sizeof(MailIndexHeader)))
+		return FALSE;
+
+	offset = sizeof(data_hdr);
+	rec = index->lookup(index, 1);
+	while (rec != NULL) {
+		if (rec->data_position + rec->data_size > mmap_data_size) {
+			index_set_error(index, "Error in index file %s: "
+					"data_position+data_size points "
+					"outside file", index->filepath);
+			return FALSE;
+		}
+
+		if (write_full(fd, mmap_data + rec->data_position,
+			       rec->data_size) < 0) {
+			index_set_error(index, "Error writing to temp index "
+					"data %s: %m", path);
+			return FALSE;
+		}
+
+		rec->data_position = offset;
+		offset += rec->data_size;
+
+		rec = index->next(index, rec);
+	}
+
+	return TRUE;
+}
+
+int mail_index_compress_data(MailIndex *index)
+{
 	const char *temppath, *datapath;
 	int fd;
 
@@ -83,52 +136,16 @@
 	if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE))
 		return FALSE;
 
-	mmap_data = mail_index_data_get_mmaped(index->data, &mmap_data_size);
-	if (mmap_data == NULL)
-		return FALSE;
-
 	fd = mail_index_create_temp_file(index, &temppath);
 	if (fd == -1)
 		return FALSE;
 
-	/* write data header */
-	memset(&data_hdr, 0, sizeof(data_hdr));
-	data_hdr.indexid = index->indexid;
-	if (write_full(fd, &data_hdr, sizeof(data_hdr)) < 0) {
-		index_set_error(index, "Error writing to temp index data "
-				"%s: %m", temppath);
-		(void)close(fd);
-		(void)unlink(temppath);
-		return FALSE;
-	}
-
-	/* no we'll begin the actual moving. keep rebuild-flag on
-	   while doing it. */
-	index->header->flags |= MAIL_INDEX_FLAG_REBUILD;
-	if (!mail_index_fmsync(index, sizeof(MailIndexHeader))) {
+	if (!mail_index_copy_data(index, fd, temppath)) {
 		(void)close(fd);
 		(void)unlink(temppath);
 		return FALSE;
 	}
 
-	offset = sizeof(data_hdr);
-	rec = index->lookup(index, 1);
-	while (rec != NULL) {
-		if (write_full(fd, mmap_data + rec->data_position,
-			       rec->data_size) < 0) {
-			index_set_error(index, "Error writing to temp index "
-					"data %s: %m", temppath);
-			(void)close(fd);
-			(void)unlink(temppath);
-			return FALSE;
-		}
-
-		rec->data_position = offset;
-		offset += rec->data_size;
-
-		rec = index->next(index, rec);
-	}
-
 	/* now, close the old data file and rename the temp file into
 	   new data file */
 	mail_index_data_free(index->data);
--- a/src/lib-index/mail-index-data.c	Tue Aug 27 06:33:10 2002 +0300
+++ b/src/lib-index/mail-index-data.c	Tue Aug 27 06:36:09 2002 +0300
@@ -70,8 +70,7 @@
 			/* doesn't exist, rebuild the index */
 			INDEX_MARK_CORRUPTED(index);
 		}
-		index_set_error(index, "Can't open index data %s: %m",
-				path);
+		index_set_error(index, "Can't open index data %s: %m", path);
 		return FALSE;
 	}
 
@@ -161,7 +160,7 @@
 	data->index->data = NULL;
 
 	if (data->mmap_base != NULL) {
-		munmap(data->mmap_base, data->mmap_length);
+		(void)munmap(data->mmap_base, data->mmap_length);
 		data->mmap_base = NULL;
 	}
 
@@ -204,7 +203,8 @@
 	data->dirty_mmap = TRUE;
 }
 
-off_t mail_index_data_append(MailIndexData *data, void *buffer, size_t size)
+off_t mail_index_data_append(MailIndexData *data, const void *buffer,
+			     size_t size)
 {
 	off_t pos;
 
@@ -231,10 +231,11 @@
 				      unsigned int data_size)
 {
 	MailIndexDataHeader *hdr;
-	unsigned int max_del_space;
+	off_t max_del_space;
 
 	i_assert(data->index->lock_type == MAIL_LOCK_EXCLUSIVE);
 
+	/* make sure the whole file is mmaped */
 	if (!mmap_update(data, 0, 0))
 		return FALSE;
 
@@ -244,7 +245,7 @@
 	/* see if we've reached the max. deleted space in file */
 	if (data->mmap_length >= COMPRESS_MIN_SIZE) {
 		max_del_space = data->mmap_length / 100 * COMPRESS_PERCENTAGE;
-		if (hdr->deleted_space >= (off_t)max_del_space)
+		if (hdr->deleted_space >= max_del_space)
 			data->index->set_flags |= MAIL_INDEX_FLAG_COMPRESS_DATA;
 	}
 	return TRUE;
@@ -274,7 +275,7 @@
 		       MailField field)
 {
 	MailIndexDataRecord *rec;
-	size_t pos, max_pos;
+	off_t pos, max_pos;
 
 	if (index_rec->data_position == 0) {
 		index_reset_error(data->index);
@@ -285,7 +286,7 @@
 		return NULL;
 
 	max_pos = index_rec->data_position + (off_t)index_rec->data_size;
-	if (max_pos > data->mmap_length) {
+	if (max_pos > (off_t)data->mmap_length) {
 		INDEX_MARK_CORRUPTED(data->index);
 		index_set_error(data->index, "Error in data file %s: "
 				"Given data size larger than file size "
@@ -297,9 +298,18 @@
 
 	pos = index_rec->data_position;
 	do {
-		rec = (MailIndexDataRecord *) ((char *) data->mmap_base + pos);
+		if (pos + (off_t)sizeof(MailIndexDataRecord) > max_pos) {
+			INDEX_MARK_CORRUPTED(data->index);
+			index_set_error(data->index, "Error in data file %s: "
+					"Index points outside file "
+					"(%lu > %lu)", data->filepath,
+					(unsigned long) pos,
+					(unsigned long) data->mmap_length);
+			break;
+		}
 
-		if (pos + rec->full_field_size > max_pos) {
+		rec = (MailIndexDataRecord *) ((char *) data->mmap_base + pos);
+		if (pos + (off_t)DATA_RECORD_SIZE(rec) > max_pos) {
 			INDEX_MARK_CORRUPTED(data->index);
 			index_set_error(data->index, "Error in data file %s: "
 					"Field size points outside file "
@@ -330,13 +340,13 @@
 mail_index_data_next(MailIndexData *data, MailIndexRecord *index_rec,
 		     MailIndexDataRecord *rec)
 {
-	size_t pos, max_pos;
+	off_t pos, max_pos;
 
 	if (rec == NULL)
 		return NULL;
 
 	/* get position to next record */
-	pos = DATA_FILE_POSITION(data, rec) + (off_t)DATA_RECORD_SIZE(rec);
+	pos = DATA_FILE_POSITION(data, rec) + DATA_RECORD_SIZE(rec);
 	max_pos = index_rec->data_position + index_rec->data_size;
 
 	/* make sure it's within range */
@@ -344,7 +354,7 @@
 		return NULL;
 
 	rec = (MailIndexDataRecord *) ((char *) data->mmap_base + pos);
-	if (pos + rec->full_field_size > max_pos) {
+	if (pos + (off_t)DATA_RECORD_SIZE(rec) > max_pos) {
 		INDEX_MARK_CORRUPTED(data->index);
 		index_set_error(data->index, "Error in data file %s: "
 				"Field size points outside file "
--- a/src/lib-index/mail-index-data.h	Tue Aug 27 06:33:10 2002 +0300
+++ b/src/lib-index/mail-index-data.h	Tue Aug 27 06:36:09 2002 +0300
@@ -16,7 +16,8 @@
 
 /* Append new data at the end of the file. Returns the position in file
    where the data begins, or (off_t)-1 if error occured. */
-off_t mail_index_data_append(MailIndexData *data, void *buffer, size_t size);
+off_t mail_index_data_append(MailIndexData *data, const void *buffer,
+			     size_t size);
 
 /* Increase header->deleted_space field */
 int mail_index_data_add_deleted_space(MailIndexData *data,
--- a/src/lib-index/mail-index-update-cache.c	Tue Aug 27 06:33:10 2002 +0300
+++ b/src/lib-index/mail-index-update-cache.c	Tue Aug 27 06:36:09 2002 +0300
@@ -28,7 +28,7 @@
 	if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE))
 		return FALSE;
 
-	cache_fields = index->get_header(index)->cache_fields;
+	cache_fields = index->header->cache_fields;
 
 	rec = index->lookup(index, 1);
 	while (rec != NULL) {
--- a/src/lib-index/mail-index.h	Tue Aug 27 06:33:10 2002 +0300
+++ b/src/lib-index/mail-index.h	Tue Aug 27 06:36:09 2002 +0300
@@ -117,9 +117,9 @@
 	unsigned int data_size;
 
 	unsigned int cached_fields;
-	unsigned int header_size;
-	unsigned int body_size;
-	unsigned int full_virtual_size;
+	off_t header_size;
+	off_t body_size;
+	off_t full_virtual_size;
 };
 
 #define MSG_HAS_VALID_CRLF_DATA(rec) \