]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-mail: rfc822_parse_content_param() was unescaping already unescaped parameters
authorTimo Sirainen <tss@iki.fi>
Mon, 30 Nov 2015 11:14:29 +0000 (13:14 +0200)
committerTimo Sirainen <tss@iki.fi>
Mon, 30 Nov 2015 11:14:29 +0000 (13:14 +0200)
This caused all Content-* parameter parsing to be unescaped once too many
times, resulting in somewhat broken BODY and BODYSTRUCTURE replies if any
<\> characters were used. Also MIME boundaries were parsed in case <\> was
used in them, but this probably didn't practically happen.

src/lib-mail/Makefile.am
src/lib-mail/rfc822-parser.c
src/lib-mail/test-rfc822-parser.c [new file with mode: 0644]

index 6a3510afc65f193e0b24caf5ebe37394aa739f5a..7ae5a9d3ea2b1e044c1c3fca177346108fd728ea 100644 (file)
@@ -95,7 +95,8 @@ test_programs = \
        test-ostream-dot \
        test-qp-decoder \
        test-quoted-printable \
-       test-rfc2231-parser
+       test-rfc2231-parser \
+       test-rfc822-parser
 
 noinst_PROGRAMS = $(test_programs)
 
@@ -196,6 +197,10 @@ test_rfc2231_parser_SOURCES = test-rfc2231-parser.c
 test_rfc2231_parser_LDADD = rfc2231-parser.lo rfc822-parser.lo $(test_libs)
 test_rfc2231_parser_DEPENDENCIES = $(test_deps)
 
+test_rfc822_parser_SOURCES = test-rfc822-parser.c
+test_rfc822_parser_LDADD = rfc822-parser.lo $(test_libs)
+test_rfc822_parser_DEPENDENCIES = $(test_deps)
+
 check: check-am check-test
 check-test: all-am
        for bin in $(test_programs); do \
index 21e95fa3cc4621f2b18d278d17ca25cb2a180aa2..7bc387631023f3e93bb6d0c3cc2ab7bd86daabf0 100644 (file)
@@ -409,7 +409,6 @@ int rfc822_parse_content_param(struct rfc822_parser_context *ctx,
                /* broken / no value */
        } else if (*ctx->data == '"') {
                ret = rfc822_parse_quoted_string(ctx, tmp);
-               (void)str_unescape(str_c_modifiable(tmp) + value_pos);
        } else if (ctx->data != ctx->end && *ctx->data == '=') {
                /* workaround for broken input:
                   name==?utf-8?b?...?= */
diff --git a/src/lib-mail/test-rfc822-parser.c b/src/lib-mail/test-rfc822-parser.c
new file mode 100644 (file)
index 0000000..70a871b
--- /dev/null
@@ -0,0 +1,74 @@
+/* Copyright (c) 2015 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "str.h"
+#include "rfc822-parser.h"
+#include "test-common.h"
+
+static void test_rfc822_parse_quoted_string(void)
+{
+       const struct {
+               const char *input, *output;
+               int ret;
+       } tests[] = {
+               { "\"", "", -1 },
+               { "\"\"", "", 0 },
+               { "\"foo\"", "foo", 0 },
+               { "\"\"foo", "", 1 },
+               { "\"\"\"", "", 1 },
+               { "\"\\\"\"", "\"", 0 },
+               { "\"\\\\\"", "\\", 0 },
+               { "\"\\\\foo\\\\foo\\\\\"", "\\foo\\foo\\", 0 }
+       };
+       struct rfc822_parser_context parser;
+       string_t *str = t_str_new(64);
+       unsigned int i = 0;
+
+       test_begin("rfc822 parse quoted string");
+       for (i = 0; i < N_ELEMENTS(tests); i++) {
+               rfc822_parser_init(&parser, (const void *)tests[i].input,
+                                  strlen(tests[i].input), NULL);
+               test_assert_idx(rfc822_parse_quoted_string(&parser, str) == tests[i].ret, i);
+               test_assert_idx(tests[i].ret < 0 ||
+                               strcmp(tests[i].output, str_c(str)) == 0, i);
+               str_truncate(str, 0);
+       }
+       test_end();
+}
+
+static void test_rfc822_parse_content_param(void)
+{
+       const char *input =
+               "; key1=value1#$!%&'*+-.^_`{|}~"
+               "; key2=\" \\\"(),/:;<=>?@[\\\\]\"";
+       const struct {
+               const char *key, *value;
+       } output[] = {
+               { "key1", "value1#$!%&'*+-.^_`{|}~" },
+               { "key2", " \"(),/:;<=>?@[\\]" }
+       };
+       struct rfc822_parser_context parser;
+       const char *key, *value;
+       unsigned int i = 0;
+       int ret;
+
+       test_begin("rfc822 parse content param");
+       rfc822_parser_init(&parser, (const void *)input, strlen(input), NULL);
+       while ((ret = rfc822_parse_content_param(&parser, &key, &value)) > 0) {
+               test_assert_idx(strcmp(output[i].key, key) == 0, i);
+               test_assert_idx(strcmp(output[i].value, value) == 0, i);
+               i++;
+       }
+       test_assert(ret == 0);
+       test_end();
+}
+
+int main(void)
+{
+       static void (*test_functions[])(void) = {
+               test_rfc822_parse_quoted_string,
+               test_rfc822_parse_content_param,
+               NULL
+       };
+       return test_run(test_functions);
+}