dovecot-1.1: Changed message_parser_deinit() to return -1 if the...

dovecot at dovecot.org dovecot at dovecot.org
Thu Feb 14 22:43:28 EET 2008


details:   http://hg.dovecot.org/dovecot-1.1/rev/289765861d66
changeset: 7243:289765861d66
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Feb 14 22:43:28 2008 +0200
description:
Changed message_parser_deinit() to return -1 if the parser was using
preparsed broken message parts. Callers catch the error and mark the cache
file corrupted.

diffstat:

7 files changed, 51 insertions(+), 16 deletions(-)
src/lib-mail/message-parser.c              |   15 ++++++++++++---
src/lib-mail/message-parser.h              |    5 ++++-
src/lib-mail/message-search.c              |   17 +++++++++++++----
src/lib-storage/index/index-mail-headers.c |    3 ++-
src/lib-storage/index/index-mail.c         |   16 +++++++++++++---
src/plugins/fts/fts-storage.c              |    5 +++--
src/tests/test-mail.c                      |    6 ++++--

diffs (197 lines):

diff -r 8cfa61f98e32 -r 289765861d66 src/lib-mail/message-parser.c
--- a/src/lib-mail/message-parser.c	Thu Feb 14 22:40:23 2008 +0200
+++ b/src/lib-mail/message-parser.c	Thu Feb 14 22:43:28 2008 +0200
@@ -41,6 +41,7 @@ struct message_parser_ctx {
 				struct message_block *block_r);
 
 	unsigned int part_seen_content_type:1;
+	unsigned int broken:1;
 };
 
 message_part_header_callback_t *null_message_part_header_callback = NULL;
@@ -663,6 +664,11 @@ static int preparsed_parse_next_header(s
 	/* return empty block as end of headers */
 	block_r->hdr = NULL;
 	block_r->size = 0;
+
+	i_assert(ctx->skip == 0);
+	if (ctx->input->v_offset != ctx->part->physical_pos +
+	    ctx->part->header_size.physical_size)
+		ctx->broken = TRUE;
 	return 1;
 }
 
@@ -718,15 +724,18 @@ message_parser_init_from_parts(struct me
 	return ctx;
 }
 
-struct message_part *message_parser_deinit(struct message_parser_ctx **_ctx)
+int message_parser_deinit(struct message_parser_ctx **_ctx,
+			  struct message_part **parts_r)
 {
         struct message_parser_ctx *ctx = *_ctx;
-	struct message_part *parts = ctx->parts;
+	int ret = ctx->broken ? -1 : 0;
 
 	*_ctx = NULL;
+	*parts_r = ctx->parts;
+
 	i_stream_unref(&ctx->input);
 	pool_unref(&ctx->parser_pool);
-	return parts;
+	return ret;
 }
 
 int message_parser_parse_next_block(struct message_parser_ctx *ctx,
diff -r 8cfa61f98e32 -r 289765861d66 src/lib-mail/message-parser.h
--- a/src/lib-mail/message-parser.h	Thu Feb 14 22:40:23 2008 +0200
+++ b/src/lib-mail/message-parser.h	Thu Feb 14 22:43:28 2008 +0200
@@ -78,7 +78,10 @@ message_parser_init_from_parts(struct me
 			       struct istream *input,
 			       enum message_header_parser_flags hdr_flags,
 			       enum message_parser_flags flags);
-struct message_part *message_parser_deinit(struct message_parser_ctx **ctx);
+/* Returns 0 if parts were returned, -1 we used preparsed parts and they
+   didn't match the current message */
+int message_parser_deinit(struct message_parser_ctx **ctx,
+			  struct message_part **parts_r);
 
 /* Read the next block of a message. Returns 1 if block is returned, 0 if
    input stream is non-blocking and more data needs to be read, -1 when all is
diff -r 8cfa61f98e32 -r 289765861d66 src/lib-mail/message-search.c
--- a/src/lib-mail/message-search.c	Thu Feb 14 22:40:23 2008 +0200
+++ b/src/lib-mail/message-search.c	Thu Feb 14 22:43:28 2008 +0200
@@ -214,7 +214,8 @@ message_search_msg_real(struct message_s
 		MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE;
 	struct message_parser_ctx *parser_ctx;
 	struct message_block raw_block;
-	int ret = 0;
+	struct message_part *new_parts;
+	int ret;
 
 	message_search_reset(ctx);
 
@@ -229,13 +230,21 @@ message_search_msg_real(struct message_s
 
 	while ((ret = message_parser_parse_next_block(parser_ctx,
 						      &raw_block)) > 0) {
-		if ((ret = message_search_more(ctx, &raw_block)) != 0)
+		if (message_search_more(ctx, &raw_block)) {
+			ret = 1;
 			break;
+		}
 	}
 	i_assert(ret != 0);
-	if (ret < 0 && input->stream_errno == 0)
+	if (ret < 0 && input->stream_errno == 0) {
+		/* normal exit */
 		ret = 0;
-	(void)message_parser_deinit(&parser_ctx);
+	}
+	if (message_parser_deinit(&parser_ctx, &new_parts) < 0) {
+		/* broken parts */
+		input->stream_errno = 0;
+		ret = -1;
+	}
 	return ret;
 }
 
diff -r 8cfa61f98e32 -r 289765861d66 src/lib-storage/index/index-mail-headers.c
--- a/src/lib-storage/index/index-mail-headers.c	Thu Feb 14 22:40:23 2008 +0200
+++ b/src/lib-storage/index/index-mail-headers.c	Thu Feb 14 22:43:28 2008 +0200
@@ -380,9 +380,10 @@ static void index_mail_init_parser(struc
 static void index_mail_init_parser(struct index_mail *mail)
 {
 	struct index_mail_data *data = &mail->data;
+	struct message_part *parts;
 
 	if (data->parser_ctx != NULL)
-		(void)message_parser_deinit(&data->parser_ctx);
+		(void)message_parser_deinit(&data->parser_ctx, &parts);
 
 	if (data->parts == NULL) {
 		data->parser_ctx = message_parser_init(mail->data_pool,
diff -r 8cfa61f98e32 -r 289765861d66 src/lib-storage/index/index-mail.c
--- a/src/lib-storage/index/index-mail.c	Thu Feb 14 22:40:23 2008 +0200
+++ b/src/lib-storage/index/index-mail.c	Thu Feb 14 22:43:28 2008 +0200
@@ -702,7 +702,12 @@ static void index_mail_parse_body_finish
 static void index_mail_parse_body_finish(struct index_mail *mail,
 					 enum index_cache_field field)
 {
-	mail->data.parts = message_parser_deinit(&mail->data.parser_ctx);
+	if (message_parser_deinit(&mail->data.parser_ctx,
+				  &mail->data.parts) < 0) {
+		mail_set_cache_corrupted(&mail->mail.mail,
+					 MAIL_FETCH_MESSAGE_PARTS);
+		return;
+	}
 
 	(void)get_cached_msgpart_sizes(mail);
 
@@ -1026,14 +1031,19 @@ void index_mail_close(struct mail *_mail
 void index_mail_close(struct mail *_mail)
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
+	struct message_part *parts;
 
 	if (mail->mail.mail.seq != 0) {
 		index_mail_cache_sizes(mail);
 		index_mail_cache_dates(mail);
 	}
 
-	if (mail->data.parser_ctx != NULL)
-		(void)message_parser_deinit(&mail->data.parser_ctx);
+	if (mail->data.parser_ctx != NULL) {
+		if (message_parser_deinit(&mail->data.parser_ctx, &parts) < 0) {
+			mail_set_cache_corrupted(_mail,
+						 MAIL_FETCH_MESSAGE_PARTS);
+		}
+	}
 	if (mail->data.filter_stream != NULL)
 		i_stream_unref(&mail->data.filter_stream);
 	if (mail->data.stream != NULL) {
diff -r 8cfa61f98e32 -r 289765861d66 src/plugins/fts/fts-storage.c
--- a/src/plugins/fts/fts-storage.c	Thu Feb 14 22:40:23 2008 +0200
+++ b/src/plugins/fts/fts-storage.c	Thu Feb 14 22:43:28 2008 +0200
@@ -108,7 +108,7 @@ static int fts_build_mail(struct fts_sto
 	struct message_parser_ctx *parser;
 	struct message_decoder_context *decoder;
 	struct message_block raw_block, block;
-	struct message_part *prev_part;
+	struct message_part *prev_part, *parts;
 	int ret;
 
 	ctx->uid = uid;
@@ -153,7 +153,8 @@ static int fts_build_mail(struct fts_sto
 			}
 		}
 	}
-	(void)message_parser_deinit(&parser);
+	if (message_parser_deinit(&parser, &parts) < 0)
+		mail_set_cache_corrupted(ctx->mail, MAIL_FETCH_MESSAGE_PARTS);
 	message_decoder_deinit(&decoder);
 
 	if (ret == 0) {
diff -r 8cfa61f98e32 -r 289765861d66 src/tests/test-mail.c
--- a/src/tests/test-mail.c	Thu Feb 14 22:40:23 2008 +0200
+++ b/src/tests/test-mail.c	Thu Feb 14 22:43:28 2008 +0200
@@ -219,7 +219,8 @@ static void test_message_parser(void)
 	parser = message_parser_init(pool, input, 0, 0);
 	while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ;
 	i_assert(ret < 0);
-	parts = message_parser_deinit(&parser);
+	ret = message_parser_deinit(&parser, &parts);
+	i_assert(ret == 0);
 	i_stream_unref(&input);
 
 	input = test_istream_create(test_msg);
@@ -234,7 +235,8 @@ static void test_message_parser(void)
 			break;
 		}
 	}
-	parts2 = message_parser_deinit(&parser);
+	ret = message_parser_deinit(&parser, &parts2);
+	i_assert(ret == 0);
 	i_stream_unref(&input);
 
 	if (!msg_parts_cmp(parts, parts2))


More information about the dovecot-cvs mailing list