[dovecot-cvs] dovecot/src/lib-imap imap-bodystructure.c,1.36,1.37 imap-envelope.c,1.28,1.29 imap-parser.c,1.45,1.46 imap-parser.h,1.13,1.14

cras at procontrol.fi cras at procontrol.fi
Wed Jul 2 04:57:27 EEST 2003


Update of /home/cvs/dovecot/src/lib-imap
In directory danu:/tmp/cvs-serv31549/lib-imap

Modified Files:
	imap-bodystructure.c imap-envelope.c imap-parser.c 
	imap-parser.h 
Log Message:
IMAP parser memory limits are now enforced by bytes per line rather than
limiting maximum amount of tokens per line. Default is 64k now, which should
help with the huge message sets generated by some clients.



Index: imap-bodystructure.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-imap/imap-bodystructure.c,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -d -r1.36 -r1.37
--- imap-bodystructure.c	23 Jun 2003 18:22:48 -0000	1.36
+++ imap-bodystructure.c	2 Jul 2003 00:57:25 -0000	1.37
@@ -679,7 +679,7 @@
 	input = i_stream_create_from_data(data_stack_pool, bodystructure, len);
 	(void)i_stream_read(input);
 
-	parser = imap_parser_create(input, NULL, 0, (size_t)-1);
+	parser = imap_parser_create(input, NULL, (size_t)-1);
 	ret = imap_parser_read_args(parser, 0, IMAP_PARSE_FLAG_NO_UNESCAPE |
 				    IMAP_PARSE_FLAG_LITERAL_TYPE, &args);
 

Index: imap-envelope.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-imap/imap-envelope.c,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -d -r1.28 -r1.29
--- imap-envelope.c	23 Jun 2003 18:22:48 -0000	1.28
+++ imap-envelope.c	2 Jul 2003 00:57:25 -0000	1.29
@@ -368,7 +368,7 @@
 
 	input = i_stream_create_from_data(data_stack_pool, envelope,
 					  strlen(envelope));
-	parser = imap_parser_create(input, NULL, (size_t)-1, (size_t)-1);
+	parser = imap_parser_create(input, NULL, (size_t)-1);
 
 	(void)i_stream_read(input);
 	ret = imap_parser_read_args(parser, field+1, 0, &args);

Index: imap-parser.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-imap/imap-parser.c,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -d -r1.45 -r1.46
--- imap-parser.c	20 Mar 2003 19:06:05 -0000	1.45
+++ imap-parser.c	2 Jul 2003 00:57:25 -0000	1.46
@@ -28,11 +28,12 @@
 	pool_t pool;
 	struct istream *input;
 	struct ostream *output;
-	size_t max_literal_size, max_elements;
+	size_t max_line_size;
         enum imap_parser_flags flags;
 
 	/* reset by imap_parser_reset(): */
-        struct imap_arg_list *root_list;
+	size_t line_size;
+	struct imap_arg_list *root_list;
         struct imap_arg_list *cur_list;
 	struct imap_arg *list_arg;
 	size_t element_count;
@@ -73,7 +74,7 @@
 
 struct imap_parser *
 imap_parser_create(struct istream *input, struct ostream *output,
-		   size_t max_literal_size, size_t max_elements)
+		   size_t max_line_size)
 {
 	struct imap_parser *parser;
 
@@ -81,8 +82,7 @@
         parser->pool = pool_alloconly_create("IMAP parser", 8192);
 	parser->input = input;
 	parser->output = output;
-	parser->max_literal_size = max_literal_size;
-	parser->max_elements = max_elements;
+	parser->max_line_size = max_line_size;
 
 	imap_args_realloc(parser, LIST_ALLOC_SIZE);
 	return parser;
@@ -98,6 +98,8 @@
 {
 	p_clear(parser->pool);
 
+	parser->line_size = 0;
+
 	parser->root_list = NULL;
 	parser->cur_list = NULL;
 	parser->list_arg = NULL;
@@ -136,6 +138,7 @@
 			break;
 	}
 
+	parser->line_size += i;
         i_stream_skip(parser->input, i);
 	parser->cur_pos = 0;
 
@@ -352,7 +355,9 @@
 static int imap_parser_literal_end(struct imap_parser *parser)
 {
 	if ((parser->flags & IMAP_PARSE_FLAG_LITERAL_SIZE) == 0) {
-		if (parser->literal_size > parser->max_literal_size) {
+		if (parser->line_size >= parser->max_line_size ||
+		    parser->literal_size >
+		    parser->max_line_size - parser->line_size) {
 			/* too long string, abort. */
 			parser->error = "Literal size too large";
 			parser->fatal_error = TRUE;
@@ -381,6 +386,7 @@
 	/* expecting digits + "}" */
 	for (i = parser->cur_pos; i < data_size; i++) {
 		if (data[i] == '}') {
+			parser->line_size += i+1;
 			i_stream_skip(parser->input, i+1);
 			return imap_parser_literal_end(parser);
 		}
@@ -424,6 +430,7 @@
 			return FALSE;
 
 		if (*data == '\r') {
+			parser->line_size++;
 			data++; data_size--;
 			i_stream_skip(parser->input, 1);
 
@@ -436,8 +443,10 @@
 			return FALSE;
 		}
 
+		parser->line_size++;
 		data++; data_size--;
 		i_stream_skip(parser->input, 1);
+
 		parser->literal_skip_crlf = FALSE;
 
 		i_assert(parser->cur_pos == 0);
@@ -564,14 +573,15 @@
 		if (!imap_parser_read_arg(parser))
 			break;
 
-		if (parser->element_count > parser->max_elements) {
-			parser->error = "Too many argument elements";
+		if (parser->line_size > parser->max_line_size) {
+			parser->error = "IMAP command line too large";
 			break;
 		}
 	}
 
 	if (parser->error != NULL) {
 		/* error, abort */
+		parser->line_size += parser->cur_pos;
 		i_stream_skip(parser->input, parser->cur_pos);
 		parser->cur_pos = 0;
 		*args = NULL;
@@ -579,6 +589,7 @@
 	} else if ((!IS_UNFINISHED(parser) && count > 0 &&
 		    parser->root_list->size >= count) || parser->eol) {
 		/* all arguments read / end of line. */
+		parser->line_size += parser->cur_pos;
  		i_stream_skip(parser->input, parser->cur_pos);
 		parser->cur_pos = 0;
 
@@ -621,27 +632,9 @@
 	}
 
 	if (i < data_size) {
-		i_stream_skip(parser->input, i + (data[i] == ' ' ? 1 : 0));
-		return p_strndup(parser->pool, data, i);
-	} else {
-		return NULL;
-	}
-}
-
-const char *imap_parser_read_line(struct imap_parser *parser)
-{
-	const unsigned char *data;
-	size_t i, data_size;
-
-	data = i_stream_get_data(parser->input, &data_size);
-
-	for (i = 0; i < data_size; i++) {
-		if (data[i] == '\r' || data[i] == '\n')
-			break;
-	}
-
-	if (i < data_size) {
-		i_stream_skip(parser->input, i);
+		data_size = i + (data[i] == ' ' ? 1 : 0);
+		parser->line_size += data_size;
+		i_stream_skip(parser->input, data_size);
 		return p_strndup(parser->pool, data, i);
 	} else {
 		return NULL;

Index: imap-parser.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-imap/imap-parser.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- imap-parser.h	8 Feb 2003 10:44:01 -0000	1.13
+++ imap-parser.h	2 Jul 2003 00:57:25 -0000	1.14
@@ -60,15 +60,20 @@
 	struct imap_arg args[1]; /* variable size */
 };
 
-/* Create new IMAP argument parser. There's no limit in argument sizes, only
-   the maximum buffer size of input stream limits it. max_literal_size limits
-   the maximum size of internally handled literals (ie. FLAG_LITERAL_SIZE is
-   unset). max_elements sets the number of elements we allow entirely so that
-   user can't give huge lists or lists inside lists. output is used for sending
-   command continuation requests for literals. */
+/* Create new IMAP argument parser. output is used for sending command
+   continuation requests for literals.
+
+   max_line_size can be used to approximately limit the maximum amount of
+   memory that gets allocated when parsing a line. Input buffer size limits
+   the maximum size of each parsed token.
+
+   Usually the largest lines are large only because they have a one huge
+   message set token, so you'll probably want to keep input buffer size the
+   same as max_line_size. That means the maximum memory usage is around
+   2 * max_line_size. */
 struct imap_parser *
 imap_parser_create(struct istream *input, struct ostream *output,
-		   size_t max_literal_size, size_t max_elements);
+		   size_t max_line_size);
 void imap_parser_destroy(struct imap_parser *parser);
 
 /* Reset the parser to initial state. */
@@ -93,9 +98,6 @@
 /* Read one word - used for reading tag and command name.
    Returns NULL if more data is needed. */
 const char *imap_parser_read_word(struct imap_parser *parser);
-
-/* Read the rest of the line. Returns NULL if more data is needed. */
-const char *imap_parser_read_line(struct imap_parser *parser);
 
 /* Returns the imap argument as string. NIL returns "" and list returns NULL. */
 const char *imap_arg_string(struct imap_arg *arg);



More information about the dovecot-cvs mailing list