changeset 10207:ee3f9bc4f5b7 HEAD

message header parser: Fixed parsing lines larger than input buffer.
author Timo Sirainen <tss@iki.fi>
date Tue, 27 Oct 2009 16:04:22 -0400
parents 86110f830311
children 233cda69b00a
files src/lib-mail/message-header-parser.c src/lib-mail/test-message-header-parser.c
diffstat 2 files changed, 54 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-mail/message-header-parser.c	Tue Oct 27 13:49:17 2009 -0400
+++ b/src/lib-mail/message-header-parser.c	Tue Oct 27 16:04:22 2009 -0400
@@ -107,7 +107,7 @@
 				return -1;
 			}
 
-			if (size > 0 &&
+			if (size > 0 && !ctx->skip_line &&
 			    (msg[0] == '\n' ||
 			     (msg[0] == '\r' && size > 1 && msg[1] == '\n'))) {
 				/* end of headers - this mostly happens just
@@ -172,7 +172,7 @@
 				if (msg[i] > ':')
 					continue;
 
-				if (msg[i] == ':') {
+				if (msg[i] == ':' && !ctx->skip_line) {
 					colon_pos = i;
 					line->full_value_offset =
 						ctx->input->v_offset + i + 1;
@@ -203,20 +203,19 @@
 		if (i < parse_size) {
 			/* got a line */
 			if (ctx->skip_line) {
-				/* skipping a huge line */
+				/* skipping a line with a huge header name */
 				if (ctx->hdr_size != NULL) {
-					ctx->hdr_size->physical_size += i;
-					ctx->hdr_size->virtual_size += i;
+					ctx->hdr_size->lines++;
+					ctx->hdr_size->physical_size += i + 1;
+					ctx->hdr_size->virtual_size += i + 1;
 				}
-
 				if (i == 0 || msg[i-1] != '\r') {
 					/* missing CR */
 					if (ctx->hdr_size != NULL)
 						ctx->hdr_size->virtual_size++;
-				} else {
-					crlf_newline = TRUE;
 				}
-				i_stream_skip(ctx->input, i);
+
+				i_stream_skip(ctx->input, i + 1);
 				startpos = 0;
 				ctx->skip_line = FALSE;
 				continue;
--- a/src/lib-mail/test-message-header-parser.c	Tue Oct 27 13:49:17 2009 -0400
+++ b/src/lib-mail/test-message-header-parser.c	Tue Oct 27 16:04:22 2009 -0400
@@ -194,11 +194,57 @@
 	test_end();
 }
 
+static void
+test_message_header_parser_long_lines_str(const char *str,
+					  unsigned int buffer_size,
+					  struct message_size *size_r)
+{
+	struct message_header_parser_ctx *parser;
+	struct message_header_line *hdr;
+	struct istream *input;
+	unsigned int i, len = strlen(str);
+
+	input = test_istream_create(str);
+	test_istream_set_max_buffer_size(input, buffer_size);
+
+	parser = message_parse_header_init(input, size_r, 0);
+	for (i = 1; i <= len; i++) {
+		test_istream_set_size(input, i);
+		while (message_parse_header_next(parser, &hdr) > 0) ;
+	}
+	message_parse_header_deinit(&parser);
+	i_stream_unref(&input);
+}
+
+static void test_message_header_parser_long_lines(void)
+{
+	static const char *lf_str = "1234567890: 345\n\n";
+	static const char *crlf_str = "1234567890: 345\r\n\r\n";
+	struct message_size hdr_size;
+	unsigned int i, len;
+
+	test_begin("message header parser long lines");
+	len = strlen(lf_str);
+	for (i = 1; i < len; i++) {
+		test_message_header_parser_long_lines_str(lf_str, i, &hdr_size);
+		test_assert(hdr_size.physical_size == len);
+		test_assert(hdr_size.virtual_size == len + 2);
+	}
+	len = strlen(crlf_str);
+	for (i = 1; i < len; i++) {
+		test_message_header_parser_long_lines_str(crlf_str, i, &hdr_size);
+		test_assert(hdr_size.physical_size == len);
+		test_assert(hdr_size.virtual_size == len);
+	}
+	test_end();
+}
+
 int main(void)
 {
 	static void (*test_functions[])(void) = {
 		test_message_header_parser,
 		test_message_header_parser_partial,
+		test_message_header_parser_long_lines,
 		NULL
 	};
 	return test_run(test_functions);