dovecot-2.2: lib-imap: imap_append_string_for_humans() returned ...

dovecot at dovecot.org dovecot at dovecot.org
Wed May 29 16:40:55 EEST 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/714320c3cfa6
changeset: 16417:714320c3cfa6
user:      Timo Sirainen <tss at iki.fi>
date:      Wed May 29 16:40:50 2013 +0300
description:
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.

diffstat:

 src/lib-imap/Makefile.am       |   5 ++++
 src/lib-imap/imap-quote.c      |  17 +++++++++++---
 src/lib-imap/test-imap-quote.c |  47 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 65 insertions(+), 4 deletions(-)

diffs (127 lines):

diff -r f294d40a8978 -r 714320c3cfa6 src/lib-imap/Makefile.am
--- a/src/lib-imap/Makefile.am	Wed May 29 12:44:15 2013 +0300
+++ b/src/lib-imap/Makefile.am	Wed May 29 16:40:50 2013 +0300
@@ -44,6 +44,7 @@
 	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_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 -r f294d40a8978 -r 714320c3cfa6 src/lib-imap/imap-quote.c
--- a/src/lib-imap/imap-quote.c	Wed May 29 12:44:15 2013 +0300
+++ b/src/lib-imap/imap-quote.c	Wed May 29 16:40:50 2013 +0300
@@ -119,7 +119,7 @@
 				   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 @@
 			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 @@
 		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 @@
 			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 -r f294d40a8978 -r 714320c3cfa6 src/lib-imap/test-imap-quote.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-imap/test-imap-quote.c	Wed May 29 16:40:50 2013 +0300
@@ -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);
+}


More information about the dovecot-cvs mailing list