Mercurial > dovecot > core-2.2
changeset 21294:dfa20786a81d
lib-imap: imap-bodystructure: Prevent writing erroneous whitespace between items in an envelope address list.
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.
author | Stephan Bosch <stephan.bosch@dovecot.fi> |
---|---|
date | Wed, 14 Dec 2016 02:51:54 +0100 |
parents | 0b5ede227460 |
children | 75acc3287480 |
files | src/lib-imap/imap-bodystructure.c src/lib-imap/test-imap-bodystructure.c |
diffstat | 2 files changed, 20 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-imap/imap-bodystructure.c Tue Dec 13 18:31:41 2016 +0200 +++ b/src/lib-imap/imap-bodystructure.c Wed Dec 14 02:51:54 2016 +0100 @@ -547,12 +547,16 @@ 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 @@ } 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 @@ 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)); @@ -975,7 +987,7 @@ 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)) {
--- a/src/lib-imap/test-imap-bodystructure.c Tue Dec 13 18:31:41 2016 +0200 +++ b/src/lib-imap/test-imap-bodystructure.c Wed Dec 14 02:51:54 2016 +0100 @@ -31,6 +31,7 @@ "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 @@ "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) {