From: Timo Sirainen Date: Wed, 29 May 2013 13:40:50 +0000 (+0300) Subject: lib-imap: imap_append_string_for_humans() returned broken output for whitespace-only... X-Git-Tag: 2.2.3~106 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d8ce48fb2b068ceae03f8df3610e254c3ccd2b2e;p=thirdparty%2Fdovecot%2Fcore.git lib-imap: imap_append_string_for_humans() returned broken output for whitespace-only input. This returned broken IMAP ENVELOPEs, especially for subjects that contained only whitespace. Since the broken output returned a huge literal, it basically caused the IMAP client to hang. --- diff --git a/src/lib-imap/Makefile.am b/src/lib-imap/Makefile.am index 43822703b8..3d9f1a2141 100644 --- a/src/lib-imap/Makefile.am +++ b/src/lib-imap/Makefile.am @@ -44,6 +44,7 @@ test_programs = \ test-imap-bodystructure \ test-imap-match \ test-imap-parser \ + test-imap-quote \ test-imap-url \ test-imap-utf7 \ test-imap-util @@ -68,6 +69,10 @@ test_imap_parser_SOURCES = test-imap-parser.c test_imap_parser_LDADD = imap-parser.lo imap-arg.lo $(test_libs) test_imap_parser_DEPENDENCIES = $(test_deps) +test_imap_quote_SOURCES = test-imap-quote.c +test_imap_quote_LDADD = imap-quote.lo $(test_libs) +test_imap_quote_DEPENDENCIES = $(test_deps) + test_imap_url_SOURCES = test-imap-url.c test_imap_url_LDADD = imap-url.lo $(test_libs) test_imap_url_DEPENDENCIES = $(test_deps) diff --git a/src/lib-imap/imap-quote.c b/src/lib-imap/imap-quote.c index 7234df682a..73dd5d430f 100644 --- a/src/lib-imap/imap-quote.c +++ b/src/lib-imap/imap-quote.c @@ -119,7 +119,7 @@ void imap_append_string_for_humans(string_t *dest, const unsigned char *src, size_t size) { size_t i, pos, remove_count = 0; - bool last_lwsp = TRUE, modify = FALSE; + bool whitespace_prefix = TRUE, last_lwsp = TRUE, modify = FALSE; /* first check if there is anything to change */ for (i = 0; i < size; i++) { @@ -155,8 +155,10 @@ void imap_append_string_for_humans(string_t *dest, last_lwsp = FALSE; break; } + if (!last_lwsp) + whitespace_prefix = FALSE; } - if (last_lwsp && i > 0) { + if (last_lwsp && i > 0 && !whitespace_prefix) { modify = TRUE; remove_count++; } @@ -168,11 +170,16 @@ void imap_append_string_for_humans(string_t *dest, str_append_c(dest, '"'); return; } + if (size == remove_count) { + /* contained only whitespace */ + str_append(dest, "\"\""); + return; + } str_printfa(dest, "{%"PRIuSIZE_T"}\r\n", size - remove_count); pos = str_len(dest); - last_lwsp = TRUE; + last_lwsp = TRUE; whitespace_prefix = TRUE; for (i = 0; i < size; i++) { switch (src[i]) { case 0: @@ -193,8 +200,10 @@ void imap_append_string_for_humans(string_t *dest, str_append_c(dest, src[i]); break; } + if (!last_lwsp) + whitespace_prefix = FALSE; } - if (last_lwsp) + if (last_lwsp && i > 0 && !whitespace_prefix) str_truncate(dest, str_len(dest)-1); i_assert(str_len(dest) - pos == size - remove_count); } diff --git a/src/lib-imap/test-imap-quote.c b/src/lib-imap/test-imap-quote.c new file mode 100644 index 0000000000..3edb1dd99e --- /dev/null +++ b/src/lib-imap/test-imap-quote.c @@ -0,0 +1,47 @@ +/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "str.h" +#include "imap-quote.h" +#include "test-common.h" + +static void test_imap_append_string_for_humans(void) +{ + static struct { + const char *input, *output; + } tests[] = { + { "", "\"\"" }, + { " ", "\"\"" }, + { " ", "\"\"" }, + { "\t", "\"\"" }, + { " \t", "\"\"" }, + { " \t ", "\"\"" }, + { " foo", "{3}\r\nfoo" }, + { "\tfoo", "{3}\r\nfoo" }, + { "\t \tfoo", "{3}\r\nfoo" }, + { " foo ", "{3}\r\nfoo" }, + { " foo ", "{3}\r\nfoo" }, + { " foo \t \t", "{3}\r\nfoo" } + }; + string_t *str = t_str_new(128); + unsigned int i; + + test_begin("imap_append_string_for_humans()"); + + for (i = 0; i < N_ELEMENTS(tests); i++) { + str_truncate(str, 0); + imap_append_string_for_humans(str, (const void *)tests[i].input, + strlen(tests[i].input)); + test_assert(strcmp(tests[i].output, str_c(str)) == 0); + } + test_end(); +} + +int main(void) +{ + static void (*test_functions[])(void) = { + test_imap_append_string_for_humans, + NULL + }; + return test_run(test_functions); +}