]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-imap: imap-bodystructure: Prevent writing erroneous whitespace between items...
authorStephan Bosch <stephan.bosch@dovecot.fi>
Wed, 14 Dec 2016 01:51:54 +0000 (02:51 +0100)
committerGitLab <gitlab@git.dovecot.net>
Wed, 14 Dec 2016 15:28:44 +0000 (17:28 +0200)
Both imap_bodystructure_write() and imap_body_parse_from_bodystructure() produced such invalid output.
This caused an RFC 3501 violation in IMAP FETCH BODY and BODYSTRUCTURE responses.

Test suite is amended to test this situation.

src/lib-imap/imap-bodystructure.c
src/lib-imap/test-imap-bodystructure.c

index d5445d15ecddf039513487d4c8bfb61f4658c03e..857209f5e23b502d544a6b5e8d444e077d6df188 100644 (file)
@@ -547,12 +547,16 @@ get_nstring(const struct imap_arg *arg, pool_t pool, string_t *tmpstr,
        return TRUE;
 }
 
-static void imap_write_list(const struct imap_arg *args, string_t *str)
+static void
+imap_write_envelope_list(const struct imap_arg *args, string_t *str,
+       bool toplevel)
 {
        const struct imap_arg *children;
 
        /* don't do any typechecking, just write it out */
        while (!IMAP_ARG_IS_EOL(args)) {
+               bool list = FALSE;
+
                if (!str_append_nstring(str, args)) {
                        if (!imap_arg_get_list(args, &children)) {
                                /* everything is either nstring or list */
@@ -560,16 +564,24 @@ static void imap_write_list(const struct imap_arg *args, string_t *str)
                        }
 
                        str_append_c(str, '(');
-                       imap_write_list(children, str);
+                       imap_write_envelope_list(children, str, FALSE);
                        str_append_c(str, ')');
+
+                       list = TRUE;
                }
                args++;
 
-               if (!IMAP_ARG_IS_EOL(args))
+               if ((toplevel || !list) && !IMAP_ARG_IS_EOL(args))
                        str_append_c(str, ' ');
        }
 }
 
+static void
+imap_write_envelope(const struct imap_arg *args, string_t *str)
+{
+       imap_write_envelope_list(args, str, TRUE);
+}
+
 static int imap_write_nstring_list(const struct imap_arg *args, string_t *str)
 {
        str_truncate(str, 0);
@@ -814,7 +826,7 @@ imap_bodystructure_parse_args(const struct imap_arg *args, pool_t pool,
                        return -1;
                }
                str_truncate(tmpstr, 0);
-               imap_write_list(list_args, tmpstr);
+               imap_write_envelope(list_args, tmpstr);
                child_data = part->children->context;
                child_data->envelope_str = p_strdup(pool, str_c(tmpstr));
 
@@ -974,7 +986,7 @@ static int imap_parse_bodystructure_args(const struct imap_arg *args,
                        return -1;
                }
                str_append_c(str, '(');
-               imap_write_list(list_args, str);
+               imap_write_envelope(list_args, str);
                str_append(str, ") (");
 
                if (!imap_arg_get_list(&args[1], &list_args)) {
index 0df8998b123e31cb7215f29675ac5e3f7ec1dcb4..83dec59c5f338e3b8f8ce4965c5a584cd74ce877 100644 (file)
@@ -31,6 +31,7 @@ static const char testmsg[] =
 "Content-Type: message/rfc822\n"
 "\n"
 "From: sub@domain.org\n"
+"To: sub-to1@domain.org, sub-to2@domain.org\n"
 "Date: Sun, 12 Aug 2012 12:34:56 +0300\n"
 "Subject: submsg\n"
 "Content-Type: multipart/alternative; boundary=\"sub1\"\n"
@@ -55,10 +56,10 @@ static const char testmsg[] =
 "Root MIME epilogue\n";
 
 static const char testmsg_bodystructure[] =
-"(\"text\" \"x-myown\" (\"charset\" \"us-ascii\" \"foo\" \"quoted\\\"string\") \"<foo@example.com>\" \"hellodescription\" \"7bit\" 7 1 \"Q2hlY2sgSW50ZWdyaXR5IQ==\" (\"inline\" (\"foo\" \"bar\")) (\"en\" \"fi\" \"se\") \"http://example.com/test.txt\")(\"message\" \"rfc822\" NIL NIL NIL \"7bit\" 368 (\"Sun, 12 Aug 2012 12:34:56 +0300\" \"submsg\" ((NIL NIL \"sub\" \"domain.org\")) ((NIL NIL \"sub\" \"domain.org\")) ((NIL NIL \"sub\" \"domain.org\")) NIL NIL NIL NIL NIL) ((\"text\" \"html\" (\"charset\" \"us-ascii\") NIL NIL \"8bit\" 20 1 NIL NIL NIL NIL)(\"text\" \"plain\" (\"charset\" \"us-ascii\") NIL NIL \"7bit\" 21 1 NIL NIL NIL NIL) \"alternative\" (\"boundary\" \"sub1\") NIL NIL NIL) 20 NIL NIL NIL NIL) \"mixed\" (\"boundary\" \"foo bar\") NIL NIL NIL";
+"(\"text\" \"x-myown\" (\"charset\" \"us-ascii\" \"foo\" \"quoted\\\"string\") \"<foo@example.com>\" \"hellodescription\" \"7bit\" 7 1 \"Q2hlY2sgSW50ZWdyaXR5IQ==\" (\"inline\" (\"foo\" \"bar\")) (\"en\" \"fi\" \"se\") \"http://example.com/test.txt\")(\"message\" \"rfc822\" NIL NIL NIL \"7bit\" 412 (\"Sun, 12 Aug 2012 12:34:56 +0300\" \"submsg\" ((NIL NIL \"sub\" \"domain.org\")) ((NIL NIL \"sub\" \"domain.org\")) ((NIL NIL \"sub\" \"domain.org\")) ((NIL NIL \"sub-to1\" \"domain.org\")(NIL NIL \"sub-to2\" \"domain.org\")) NIL NIL NIL NIL) ((\"text\" \"html\" (\"charset\" \"us-ascii\") NIL NIL \"8bit\" 20 1 NIL NIL NIL NIL)(\"text\" \"plain\" (\"charset\" \"us-ascii\") NIL NIL \"7bit\" 21 1 NIL NIL NIL NIL) \"alternative\" (\"boundary\" \"sub1\") NIL NIL NIL) 21 NIL NIL NIL NIL) \"mixed\" (\"boundary\" \"foo bar\") NIL NIL NIL";
 
 static const char testmsg_body[] =
-"(\"text\" \"x-myown\" (\"charset\" \"us-ascii\" \"foo\" \"quoted\\\"string\") \"<foo@example.com>\" \"hellodescription\" \"7bit\" 7 1)(\"message\" \"rfc822\" NIL NIL NIL \"7bit\" 368 (\"Sun, 12 Aug 2012 12:34:56 +0300\" \"submsg\" ((NIL NIL \"sub\" \"domain.org\")) ((NIL NIL \"sub\" \"domain.org\")) ((NIL NIL \"sub\" \"domain.org\")) NIL NIL NIL NIL NIL) ((\"text\" \"html\" (\"charset\" \"us-ascii\") NIL NIL \"8bit\" 20 1)(\"text\" \"plain\" (\"charset\" \"us-ascii\") NIL NIL \"7bit\" 21 1) \"alternative\") 20) \"mixed\"";
+"(\"text\" \"x-myown\" (\"charset\" \"us-ascii\" \"foo\" \"quoted\\\"string\") \"<foo@example.com>\" \"hellodescription\" \"7bit\" 7 1)(\"message\" \"rfc822\" NIL NIL NIL \"7bit\" 412 (\"Sun, 12 Aug 2012 12:34:56 +0300\" \"submsg\" ((NIL NIL \"sub\" \"domain.org\")) ((NIL NIL \"sub\" \"domain.org\")) ((NIL NIL \"sub\" \"domain.org\")) ((NIL NIL \"sub-to1\" \"domain.org\")(NIL NIL \"sub-to2\" \"domain.org\")) NIL NIL NIL NIL) ((\"text\" \"html\" (\"charset\" \"us-ascii\") NIL NIL \"8bit\" 20 1)(\"text\" \"plain\" (\"charset\" \"us-ascii\") NIL NIL \"7bit\" 21 1) \"alternative\") 21) \"mixed\"";
 
 static struct message_part *msg_parse(pool_t pool, bool parse_bodystructure)
 {