Patch: add safety checks for accesses to camel folder summary



	Hi,

	This patch adds safety checks to camel folder summary, to avoid
crashing if the file is corrupt or is not complete.

Changelog entry:
        * Added proper error checking for summary MMAP. The THROW macro
        changed to provide appropriate error propagation mechanism.



-- 
José Dapena Paz <jdapena igalia com>
Igalia
diff --git a/libtinymail-camel/camel-lite/camel/camel-file-utils.c b/libtinymail-camel/camel-lite/camel/camel-file-utils.c
index ed183ed..8548a55 100644
--- a/libtinymail-camel/camel-lite/camel/camel-file-utils.c
+++ b/libtinymail-camel/camel-lite/camel/camel-file-utils.c
@@ -220,7 +220,7 @@ unsigned char*
 camel_file_util_mmap_decode_uint32 (unsigned char *start, guint32 *dest, gboolean is_string)
 {
 	guint32 value = 0;
-	value = g_ntohl(get_unaligned_u32(start)); start += 4;
+	value = g_ntohl(get_unaligned_u32(start)); start += 4; // #0
 	*dest = value;
 	return start;
 }
diff --git a/libtinymail-camel/camel-lite/camel/camel-folder-summary.c b/libtinymail-camel/camel-lite/camel/camel-folder-summary.c
index 6333ea3..b6de605 100644
--- a/libtinymail-camel/camel-lite/camel/camel-folder-summary.c
+++ b/libtinymail-camel/camel-lite/camel/camel-folder-summary.c
@@ -79,6 +79,8 @@
 #include <glib.h>
 #include <glib/gprintf.h>
 
+#define THROW g_assert (FALSE)
+
 static pthread_mutex_t info_lock = PTHREAD_MUTEX_INITIALIZER;
 
 /* this lock is ONLY for the standalone messageinfo stuff */
@@ -327,6 +329,7 @@ camel_folder_summary_unload_mmap (CamelFolderSummary *s)
 	if (s->file)
 		g_mapped_file_free (s->file);
 	s->file = NULL;
+	s->eof = NULL;
 
 	return;
 }
@@ -695,6 +698,7 @@ perform_content_info_load(CamelFolderSummary *s)
 		return NULL;
 
 	ptrchr = s->filepos;
+	if (s->eof < ptrchr + sizeof(guint32)) THROW;
 	ptrchr = camel_file_util_mmap_decode_uint32 ((unsigned char*)ptrchr, &count, FALSE);
 	s->filepos = ptrchr;
 
@@ -755,6 +759,7 @@ camel_folder_summary_load(CamelFolderSummary *s)
 	}
 
 	s->filepos = (unsigned char*) g_mapped_file_get_contents (s->file);
+	s->eof = s->filepos + g_mapped_file_get_length (s->file);
 
 	if ( ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_load(s) == -1)
 		goto error;
@@ -814,6 +819,7 @@ printf ("Removes %s\n", ri->uid);
 	if (s->saved_count <= 0) {
 		g_mapped_file_free (s->file);
 		s->file = NULL;
+		s->eof = NULL;
 	}
 
 	camel_operation_end (NULL);
@@ -1239,6 +1245,7 @@ camel_folder_summary_header_load(CamelFolderSummary *s)
 	}
 
 	s->filepos = (unsigned char*) g_mapped_file_get_contents (s->file);
+	s->eof = s->filepos + g_mapped_file_get_length (s->file);
 
 	ret = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_load(s);
 
@@ -1977,8 +1984,19 @@ camel_folder_summary_decode_token(CamelFolderSummary *s, char **str)
 
 	io(printf("Decode token ...\n"));
 
+	if (s->eof < ptrchr + sizeof(guint32))  {
+		io(printf ("Got premature EOF"));
+		*str = NULL;
+		return -1;
+	}
 	ptrchr = camel_file_util_mmap_decode_uint32 ((unsigned char*)ptrchr, &len, FALSE);
 
+	if (s->eof < ptrchr + len) {
+		io(printf ("Got premature EOF"));
+		*str = NULL;
+		return -1;
+	}
+
 	if (len<32) {
 
 		if (len <= 0) {
@@ -2376,9 +2394,12 @@ message_info_load(CamelFolderSummary *s, gboolean *must_add)
 
 	/* Try to find the original instance in case we are in reloading */
 
+	if (s->eof < ptrchr + sizeof(guint32)) THROW;
 	ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &len, TRUE);
-	if (len)
+	if (len) {
+		if (s->eof < ptrchr + len) THROW;
 		theuid = (char*)ptrchr;
+	}
 	ptrchr += len;
 
 	if (!s->in_reload)
@@ -2430,8 +2451,10 @@ message_info_load(CamelFolderSummary *s, gboolean *must_add)
 
 	}
 
+	if (s->eof < ptrchr + sizeof(guint32)) THROW;
 	ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &mi->size, FALSE);
 
+	if (s->eof < ptrchr + sizeof(guint32)) THROW;
 	ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &mi->flags, FALSE);
 
 	mi->flags &= ~CAMEL_MESSAGE_INFO_NEEDS_FREE;
@@ -2439,46 +2462,66 @@ message_info_load(CamelFolderSummary *s, gboolean *must_add)
 
 	s->set_extra_flags_func (s->folder, mi);
 
+	if (s->eof < ptrchr + sizeof(time_t)) THROW;
 	ptrchr = camel_file_util_mmap_decode_time_t (ptrchr, &mi->date_sent);
+	if (s->eof < ptrchr + sizeof(time_t)) THROW;
 	ptrchr = camel_file_util_mmap_decode_time_t (ptrchr, &mi->date_received);
 
+	if (s->eof < ptrchr + sizeof(guint32)) THROW;
 	ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &len, TRUE);
 
-	if (len)
+	if (len) {
+		if (s->eof < ptrchr + len) THROW;
 		mi->subject = (const char*)ptrchr;
-
+	}
 	ptrchr += len;
+
+	if (s->eof < ptrchr + sizeof(guint32)) THROW;
 	ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &len, TRUE);
 
-	if (len)
+	if (len) {
+		if (s->eof < ptrchr + len) THROW;
 		mi->from = (const char*)ptrchr;
-
+	}
 	ptrchr += len;
 
-	ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &len, TRUE);
+	if (s->eof < ptrchr + sizeof(guint32)) THROW;
+	ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &len, TRUE);  // #1
 
-	if (len)
+	if (len) {
+		if (s->eof < ptrchr + len) THROW;
 		mi->to = (const char*)ptrchr;
+	}
 	ptrchr += len;
 
+	if (s->eof < ptrchr + sizeof(guint32)) THROW;
 	ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &len, TRUE);
 
-	if (len)
+	if (len) {
+		if (s->eof < ptrchr + len) THROW;
 		mi->cc = (const char*)ptrchr;
+	}
 	ptrchr += len;
 
+	if (s->eof < ptrchr + sizeof(guint32)) THROW;
 	ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &len, TRUE);
 
-
+	if (len) {
+		if (s->eof < ptrchr + len) THROW;
+	}
 	ptrchr += len;
+
 	s->filepos = ptrchr;
 
+	if (s->eof < s->filepos + 4) THROW;
 	mi->message_id.id.part.hi = g_ntohl(get_unaligned_u32(s->filepos));
 	s->filepos += 4;
+	if (s->eof < s->filepos + 4) THROW;
 	mi->message_id.id.part.lo = g_ntohl(get_unaligned_u32(s->filepos));
 	s->filepos += 4;
 
 	ptrchr = (unsigned char*) s->filepos;
+	if (s->eof < ptrchr + sizeof(guint32)) THROW;
 	ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &count, FALSE);
 
 #ifdef NON_TINYMAIL_FEATURES
@@ -2490,6 +2533,7 @@ message_info_load(CamelFolderSummary *s, gboolean *must_add)
 
 	s->filepos = ptrchr;
 
+	if (s->eof < s->filepos + count * 8) THROW;
 #ifdef NON_TINYMAIL_FEATURES
 	for (i=0;i<count;i++) {
 		mi->references->references[i].id.part.hi = g_ntohl(get_unaligned_u32(s->filepos));
@@ -2502,30 +2546,43 @@ message_info_load(CamelFolderSummary *s, gboolean *must_add)
 #endif
 
 	ptrchr = s->filepos;
+	if (s->eof < ptrchr + sizeof(guint32)) THROW;
 	ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &count, FALSE);
 
 	for (i=0;i<count;i++)
 	{
 		char *name = NULL;
+		if (s->eof < ptrchr + sizeof(guint32)) THROW;
 		ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &len, TRUE);
-		if (len)
+		if (len) {
+			if (s->eof < ptrchr + len) THROW;
 			name = (char*) ptrchr;
+		}
 		ptrchr += len;
 	}
 
+	if (s->eof < ptrchr + sizeof(guint32)) THROW;
 	ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &count, FALSE);
+	/* Sergio, how ptrchr could be 0 ? */
 	if (!ptrchr) return NULL;
 
 	for (i=0;i<count;i++)
 	{
 		char *name = NULL, *value = NULL;
+		if (s->eof < ptrchr + sizeof(guint32)) THROW;
 		ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &len, TRUE);
-		if (len)
+		if (len) {
+			if (s->eof < ptrchr + len) THROW;
 			name = (char*)ptrchr;
+		}
 		ptrchr += len;
+
+		if (s->eof < ptrchr + sizeof(guint32)) THROW;
 		ptrchr = camel_file_util_mmap_decode_uint32 (ptrchr, &len, TRUE);
-		if (len)
+		if (len) {
+			if (s->eof < ptrchr + len) THROW;
 			value =(char*) ptrchr;
+		}
 		ptrchr += len;
 	}
 
@@ -2730,6 +2787,7 @@ content_info_load(CamelFolderSummary *s)
 	ct = camel_content_type_new(type, subtype);
 
 	ptrchr = s->filepos;
+	if (s->eof < ptrchr + sizeof(guint32)) THROW;
 	ptrchr = camel_file_util_mmap_decode_uint32 ((unsigned char*)ptrchr, &count, FALSE);
 	s->filepos = ptrchr;
 
@@ -2748,6 +2806,7 @@ content_info_load(CamelFolderSummary *s)
 	camel_folder_summary_decode_token(s, &ci->encoding);
 
 	ptrchr = s->filepos;
+	if (s->eof < ptrchr + sizeof(guint32)) THROW;
 	ptrchr = camel_file_util_mmap_decode_uint32 ((unsigned char*)ptrchr, &ci->size, FALSE);
 	s->filepos = ptrchr;
 
diff --git a/libtinymail-camel/camel-lite/camel/camel-folder-summary.h b/libtinymail-camel/camel-lite/camel/camel-folder-summary.h
index e9a7f9c..500ab5b 100644
--- a/libtinymail-camel/camel-lite/camel/camel-folder-summary.h
+++ b/libtinymail-camel/camel-lite/camel/camel-folder-summary.h
@@ -216,6 +216,7 @@ struct _CamelFolderSummary {
 	struct _CamelFolderMetaSummary *meta_summary; /* Meta summary */
 
 	GMappedFile *file;
+	gchar *eof;
 	unsigned char *filepos;
 	GMutex *hash_lock;
 	GStaticRecMutex *dump_lock;
diff --git a/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-summary.c b/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-summary.c
index 49cbc7e..20c86ec 100644
--- a/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-summary.c
+++ b/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-summary.c
@@ -225,7 +225,7 @@ message_info_load (CamelFolderSummary *s, gboolean *must_add)
 	CamelMessageInfo *info;
 	CamelImapMessageInfo *iinfo;
 
-	info = camel_imap_summary_parent->message_info_load (s, must_add);
+	info = camel_imap_summary_parent->message_info_load (s, must_add); // #3
 	iinfo = (CamelImapMessageInfo*)info;
 
 	if (info) {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]