dovecot-1.1: message parser: Cleaned up the code and another att...

dovecot at dovecot.org dovecot at dovecot.org
Sat Aug 30 15:25:00 EEST 2008


details:   http://hg.dovecot.org/dovecot-1.1/rev/83abb0ea6109
changeset: 7848:83abb0ea6109
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Aug 30 15:24:38 2008 +0300
description:
message parser: Cleaned up the code and another attempt at fixing infinite looping.

diffstat:

1 file changed, 49 insertions(+), 45 deletions(-)
src/lib-mail/message-parser.c |   94 +++++++++++++++++++++--------------------

diffs (183 lines):

diff -r 50df211455d7 -r 83abb0ea6109 src/lib-mail/message-parser.c
--- a/src/lib-mail/message-parser.c	Sat Aug 30 14:56:27 2008 +0300
+++ b/src/lib-mail/message-parser.c	Sat Aug 30 15:24:38 2008 +0300
@@ -42,6 +42,7 @@ struct message_parser_ctx {
 
 	unsigned int part_seen_content_type:1;
 	unsigned int broken:1;
+	unsigned int eof:1;
 };
 
 message_part_header_callback_t *null_message_part_header_callback = NULL;
@@ -103,7 +104,7 @@ static void parse_body_add_block(struct 
 }
 
 static int message_parser_read_more(struct message_parser_ctx *ctx,
-				    struct message_block *block_r)
+				    struct message_block *block_r, bool *full_r)
 {
 	int ret;
 
@@ -112,19 +113,32 @@ static int message_parser_read_more(stru
 		ctx->skip = 0;
 	}
 
+	*full_r = FALSE;
 	ret = i_stream_read_data(ctx->input, &block_r->data,
 				 &block_r->size, ctx->want_count);
 	if (ret <= 0) {
-		if (ret == -1 && block_r->size != 0) {
-			/* EOF, but we still have some data. return it. */
-			return 1;
-		}
-		if (ret < 0)
-			return ret;
-
-		if (!ctx->input->eof) {
-			i_assert(!ctx->input->blocking);
-			return 0;
+		switch (ret) {
+		case 0:
+			if (!ctx->input->eof) {
+				i_assert(!ctx->input->blocking);
+				return 0;
+			}
+			break;
+		case -1:
+			i_assert(ctx->input->eof ||
+				 ctx->input->stream_errno != 0);
+			ctx->eof = TRUE;
+			if (block_r->size != 0) {
+				/* EOF, but we still have some data.
+				   return it. */
+				return 1;
+			}
+			return -1;
+		case -2:
+			*full_r = TRUE;
+			break;
+		default:
+			i_unreached();
 		}
 	}
 
@@ -238,8 +252,9 @@ static int parse_next_body_skip_boundary
 {
 	size_t i;
 	int ret;
-
-	if ((ret = message_parser_read_more(ctx, block_r)) <= 0)
+	bool full;
+
+	if ((ret = message_parser_read_more(ctx, block_r, &full)) <= 0)
 		return ret;
 
 	for (i = 0; i < block_r->size; i++) {
@@ -266,11 +281,6 @@ static int parse_part_finish(struct mess
 			     struct message_block *block_r, bool first_line)
 {
 	struct message_part *part;
-
-	if (boundary == NULL) {
-		/* message ended unexpectedly */
-		return -1;
-	}
 
 	/* get back to parent MIME part, summing the child MIME part sizes
 	   into parent's body sizes */
@@ -314,12 +324,10 @@ static int parse_next_body_to_boundary(s
 	const unsigned char *data;
 	size_t i, boundary_start;
 	int ret;
-	bool eof, full;
-
-	if ((ret = message_parser_read_more(ctx, block_r)) <= 0)
+	bool full;
+
+	if ((ret = message_parser_read_more(ctx, block_r, &full)) <= 0)
 		return ret;
-	eof = ret == -1;
-	full = ret == -2;
 
 	data = block_r->data;
 	if (ctx->last_chr == '\n') {
@@ -328,10 +336,8 @@ static int parse_next_body_to_boundary(s
 		ret = boundary_line_find(ctx, block_r->data,
 					 block_r->size, full, &boundary);
 		if (ret >= 0) {
-			if (ret == 0)
-				return 0;
-
-			return parse_part_finish(ctx, boundary, block_r, TRUE);
+			return ret == 0 ? 0 :
+				parse_part_finish(ctx, boundary, block_r, TRUE);
 		}
 	}
 
@@ -374,19 +380,15 @@ static int parse_next_body_to_boundary(s
 	if (i >= block_r->size) {
 		/* the boundary wasn't found from this data block,
 		   we'll need more data. */
-		if (eof)
-			ret = -1;
-		else {
-			ret = 0;
-			ctx->want_count = (block_r->size - boundary_start) + 1;
-		}
-	} else if (ret == 0 && eof) {
-		/* we can't get any more data */
-		ret = -1;
+		ret = 0;
+		ctx->want_count = (block_r->size - boundary_start) + 1;
+	} else {
+		/* found / need more data */
+		i_assert(ret >= 0);
 	}
 	i_assert(!(ret == 0 && full));
 
-	if (ret >= 0) {
+	if (ret >= 0 && !ctx->eof) {
 		/* leave CR+LF + last line to buffer */
 		block_r->size = boundary_start;
 	}
@@ -401,9 +403,10 @@ static int parse_next_body_to_eof(struct
 static int parse_next_body_to_eof(struct message_parser_ctx *ctx,
 				  struct message_block *block_r)
 {
-	int ret;
-
-	if ((ret = message_parser_read_more(ctx, block_r)) <= 0)
+	bool full;
+	int ret;
+
+	if ((ret = message_parser_read_more(ctx, block_r, &full)) <= 0)
 		return ret;
 
 	parse_body_add_block(ctx, block_r);
@@ -602,9 +605,10 @@ static int preparsed_parse_body_more(str
 	uoff_t end_offset = ctx->part->physical_pos +
 		ctx->part->header_size.physical_size +
 		ctx->part->body_size.physical_size;
-	int ret;
-
-	if ((ret = message_parser_read_more(ctx, block_r)) <= 0)
+	bool full;
+	int ret;
+
+	if ((ret = message_parser_read_more(ctx, block_r, &full)) <= 0)
 		return ret;
 
 	if (ctx->input->v_offset + block_r->size >= end_offset) {
@@ -754,10 +758,10 @@ int message_parser_parse_next_block(stru
 				    struct message_block *block_r)
 {
 	int ret;
-	bool eof = FALSE;
+	bool eof = FALSE, full;
 
 	while ((ret = ctx->parse_next_block(ctx, block_r)) == 0) {
-		ret = message_parser_read_more(ctx, block_r);
+		ret = message_parser_read_more(ctx, block_r, &full);
 		if (ret == 0) {
 			i_assert(!ctx->input->blocking);
 			return 0;


More information about the dovecot-cvs mailing list