]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-imap: imap_append_string_for_humans() returned broken output for whitespace-only...
authorTimo Sirainen <tss@iki.fi>
Wed, 29 May 2013 13:40:50 +0000 (16:40 +0300)
committerTimo Sirainen <tss@iki.fi>
Wed, 29 May 2013 13:40:50 +0000 (16:40 +0300)
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.

src/lib-imap/Makefile.am
src/lib-imap/imap-quote.c
src/lib-imap/test-imap-quote.c [new file with mode: 0644]

index 43822703b8acd7f93ecf81257a20612749d5c14b..3d9f1a214122249c23c833f2e2c4f68be1f4e1a8 100644 (file)
@@ -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)
index 7234df682a6fd50f8f69af27276be357ada5cfbd..73dd5d430fb7eee11028d09a928dc20d1d773c7a 100644 (file)
@@ -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 (file)
index 0000000..3edb1dd
--- /dev/null
@@ -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);
+}