dovecot-1.2: If we detect cached header is corrupted while unfol...

dovecot at dovecot.org dovecot at dovecot.org
Thu Feb 19 20:08:57 EET 2009


details:   http://hg.dovecot.org/dovecot-1.2/rev/13e1c379ab63
changeset: 8749:13e1c379ab63
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Feb 19 13:08:50 2009 -0500
description:
If we detect cached header is corrupted while unfolding it, mark the cache corrupted.

diffstat:

1 file changed, 57 insertions(+), 27 deletions(-)
src/lib-storage/index/index-mail-headers.c |   84 +++++++++++++++++++---------

diffs (143 lines):

diff -r b39e85979c6a -r 13e1c379ab63 src/lib-storage/index/index-mail-headers.c
--- a/src/lib-storage/index/index-mail-headers.c	Fri Feb 13 17:44:00 2009 -0500
+++ b/src/lib-storage/index/index-mail-headers.c	Thu Feb 19 13:08:50 2009 -0500
@@ -650,8 +650,9 @@ index_mail_get_raw_headers(struct index_
 	return 0;
 }
 
-static const char *unfold_header(pool_t pool, const char *str)
-{
+static int unfold_header(pool_t pool, const char **_str)
+{
+	const char *str = *_str;
 	char *new_str;
 	unsigned int i, j;
 
@@ -660,7 +661,7 @@ static const char *unfold_header(pool_t 
 			break;
 	}
 	if (str[i] == '\0')
-		return str;
+		return 0;
 
 	/* @UNSAFE */
 	new_str = p_malloc(pool, i + strlen(str+i) + 1);
@@ -671,19 +672,25 @@ static const char *unfold_header(pool_t 
 			i++;
 			if (str[i] == '\0')
 				break;
-			i_assert(str[i] == ' ' || str[i] == '\t');
+
+			if (str[i] != ' ' && str[i] != '\t') {
+				/* corrupted */
+				return -1;
+			}
 		} else {
 			new_str[j++] = str[i];
 		}
 	}
 	new_str[j] = '\0';
-	return new_str;
-}
-
-static const char *const *
-index_mail_headers_decode(struct index_mail *mail, const char *const *list,
+	*_str = new_str;
+	return 0;
+}
+
+static int
+index_mail_headers_decode(struct index_mail *mail, const char *const **_list,
 			  unsigned int max_count)
 {
+	const char *const *list = *_list;
 	const char **decoded_list, *input;
 	unsigned int i, count;
 	string_t *str;
@@ -700,28 +707,39 @@ index_mail_headers_decode(struct index_m
 		if (message_header_decode_utf8((const unsigned char *)input,
 					       strlen(list[i]), str, FALSE))
 			input = str_c(str);
-		input = unfold_header(mail->data_pool, input);
+		if (unfold_header(mail->data_pool, &input) < 0)
+			return -1;
 		if (input == str->data)
 			input = p_strdup(mail->data_pool, input);
 		decoded_list[i] = input;
 	}
-	return decoded_list;
+	*_list = decoded_list;
+	return 0;
 }
 
 int index_mail_get_headers(struct mail *_mail, const char *field,
 			   bool decode_to_utf8, const char *const **value_r)
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
-
-	if (index_mail_get_raw_headers(mail, field, value_r) < 0)
-		return -1;
-	if (!decode_to_utf8 || **value_r == NULL)
-		return 0;
-
-	T_BEGIN {
-		*value_r = index_mail_headers_decode(mail, *value_r, -1U);
-	} T_END;
-	return 0;
+	int ret, i;
+
+	for (i = 0; i < 2; i++) {
+		if (index_mail_get_raw_headers(mail, field, value_r) < 0)
+			return -1;
+		if (!decode_to_utf8 || **value_r == NULL)
+			return 0;
+
+		T_BEGIN {
+			ret = index_mail_headers_decode(mail, value_r, -1U);
+		} T_END;
+
+		if (ret < 0) {
+			mail_cache_set_corrupted(mail->ibox->cache,
+				"Broken header %s for mail UID %u",
+				field, _mail->uid);
+		}
+	}
+	return ret;
 }
 
 int index_mail_get_first_header(struct mail *_mail, const char *field,
@@ -729,16 +747,28 @@ int index_mail_get_first_header(struct m
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
 	const char *const *list;
-
-	if (index_mail_get_raw_headers(mail, field, &list) < 0)
-		return -1;
-	if (decode_to_utf8 && list[0] != NULL) {
+	int ret, i;
+
+	for (i = 0; i < 2; i++) {
+		if (index_mail_get_raw_headers(mail, field, &list) < 0)
+			return -1;
+		if (!decode_to_utf8 || list[0] == NULL) {
+			ret = 0;
+			break;
+		}
+
 		T_BEGIN {
-			list = index_mail_headers_decode(mail, list, 1);
+			ret = index_mail_headers_decode(mail, &list, 1);
 		} T_END;
+
+		if (ret < 0) {
+			mail_cache_set_corrupted(mail->ibox->cache,
+				"Broken header %s for mail UID %u",
+				field, _mail->uid);
+		}
 	}
 	*value_r = list[0];
-	return list[0] != NULL ? 1 : 0;
+	return ret < 0 ? -1 : (list[0] != NULL ? 1 : 0);
 }
 
 static void header_cache_callback(struct message_header_line *hdr,


More information about the dovecot-cvs mailing list