]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
message header parser: Fixed parsing lines larger than input buffer.
authorTimo Sirainen <tss@iki.fi>
Tue, 27 Oct 2009 20:04:22 +0000 (16:04 -0400)
committerTimo Sirainen <tss@iki.fi>
Tue, 27 Oct 2009 20:04:22 +0000 (16:04 -0400)
--HG--
branch : HEAD

src/lib-mail/message-header-parser.c
src/lib-mail/test-message-header-parser.c

index c2cfae704fa1a634f164c456f86476789f79cb9a..18c67f705527a95ec93e293e88d22684a35409ea 100644 (file)
@@ -107,7 +107,7 @@ int message_parse_header_next(struct message_header_parser_ctx *ctx,
                                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 @@ int message_parse_header_next(struct message_header_parser_ctx *ctx,
                                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 @@ int message_parse_header_next(struct message_header_parser_ctx *ctx,
                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;
index 21789b2f80ed504917395d29aa987c2f6ec6faa6..428fa91dbfd93364161e8b8d2fb042e0641a933b 100644 (file)
@@ -194,11 +194,57 @@ static void test_message_header_parser_partial(void)
        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);