[dovecot-cvs] dovecot/src/lib-imap imap-bodystructure.c,1.20,1.21 imap-envelope.c,1.13,1.14 imap-parser.c,1.23,1.24 imap-parser.h,1.5,1.6

cras at procontrol.fi cras at procontrol.fi
Mon Dec 9 17:25:22 EET 2002


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

Modified Files:
	imap-bodystructure.c imap-envelope.c imap-parser.c 
	imap-parser.h 
Log Message:
Limited max. command argument elements to 128. Added more verbose error
messages to IMAP parser.



Index: imap-bodystructure.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-imap/imap-bodystructure.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- imap-bodystructure.c	6 Dec 2002 01:09:22 -0000	1.20
+++ imap-bodystructure.c	9 Dec 2002 15:25:20 -0000	1.21
@@ -598,7 +598,7 @@
 	input = i_stream_create_from_data(data_stack_pool, bodystructure, len);
 	(void)i_stream_read(input);
 
-	parser = imap_parser_create(input, NULL, 0);
+	parser = imap_parser_create(input, NULL, 0, (size_t)-1);
 	ret = imap_parser_read_args(parser, 0, IMAP_PARSE_FLAG_NO_UNESCAPE,
 				    &args);
 

Index: imap-envelope.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-imap/imap-envelope.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- imap-envelope.c	6 Dec 2002 01:09:22 -0000	1.13
+++ imap-envelope.c	9 Dec 2002 15:25:20 -0000	1.14
@@ -246,7 +246,7 @@
 
 	input = i_stream_create_from_data(data_stack_pool, envelope,
 					  strlen(envelope));
-	parser = imap_parser_create(input, NULL, 0);
+	parser = imap_parser_create(input, NULL, 0, (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.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- imap-parser.c	6 Dec 2002 01:09:22 -0000	1.23
+++ imap-parser.c	9 Dec 2002 15:25:20 -0000	1.24
@@ -23,13 +23,14 @@
 	Pool pool;
 	IStream *input;
 	OStream *output;
-	size_t max_literal_size;
+	size_t max_literal_size, max_elements;
         ImapParserFlags flags;
 
 	/* reset by imap_parser_reset(): */
         ImapArgList *root_list;
         ImapArgList *cur_list;
 	ImapArg *list_arg;
+	size_t element_count;
 
 	ArgParseType cur_type;
 	size_t cur_pos; /* parser position in input buffer */
@@ -37,10 +38,11 @@
 	int str_first_escape; /* ARG_PARSE_STRING: index to first '\' */
 	uoff_t literal_size; /* ARG_PARSE_LITERAL: string size */
 
+	const char *error;
+
 	unsigned int literal_skip_crlf:1;
 	unsigned int inside_bracket:1;
 	unsigned int eol:1;
-	unsigned int error:1;
 };
 
 #define LIST_REALLOC(parser, old_list, size) \
@@ -59,7 +61,7 @@
 }
 
 ImapParser *imap_parser_create(IStream *input, OStream *output,
-			       size_t max_literal_size)
+			       size_t max_literal_size, size_t max_elements)
 {
 	ImapParser *parser;
 
@@ -68,6 +70,7 @@
 	parser->input = input;
 	parser->output = output;
 	parser->max_literal_size = max_literal_size;
+	parser->max_elements = max_elements;
 
 	imap_args_realloc(parser, LIST_ALLOC_SIZE);
 	return parser;
@@ -86,6 +89,7 @@
 	parser->root_list = NULL;
 	parser->cur_list = NULL;
 	parser->list_arg = NULL;
+	parser->element_count = 0;
 
 	parser->cur_type = ARG_PARSE_NONE;
 	parser->cur_pos = 0;
@@ -93,14 +97,20 @@
 	parser->str_first_escape = 0;
 	parser->literal_size = 0;
 
+	parser->error = NULL;
+
 	parser->literal_skip_crlf = FALSE;
 	parser->inside_bracket = FALSE;
 	parser->eol = FALSE;
-	parser->error = FALSE;
 
 	imap_args_realloc(parser, LIST_ALLOC_SIZE);
 }
 
+const char *imap_parser_get_error(ImapParser *parser)
+{
+	return parser->error;
+}
+
 /* skip over everything parsed so far, plus the following whitespace */
 static int imap_parser_skip_to_next(ImapParser *parser, const char **data,
 				    size_t *data_size)
@@ -132,6 +142,7 @@
 	arg = &parser->cur_list->args[parser->cur_list->size];
 	arg->parent = parser->list_arg;
 	parser->cur_list->size++;
+	parser->element_count++;
 
 	return arg;
 }
@@ -155,7 +166,7 @@
 
 	if (parser->list_arg == NULL) {
 		/* we're not inside list */
-		parser->error = TRUE;
+		parser->error = "Unexpected ')'";
 		return FALSE;
 	}
 
@@ -234,17 +245,19 @@
 	   characters are an exception though, allow spaces inside them. */
 	for (i = parser->cur_pos; i < data_size; i++) {
 		if (parser->inside_bracket) {
-			if (data[i] == '[' || is_linebreak(data[i])) {
-				/* a) nested '[' characters not allowed
-				      (too much trouble and imap doesn't need)
-				   b) missing ']' character */
-				parser->error = TRUE;
+			if (data[i] == '[') {
+				/* nested '[' characters not allowed
+				   (too much trouble and imap doesn't need) */
+				parser->error = "Unexpected '['";
+			}
+			if (is_linebreak(data[i])) {
+				/* missing ']' character */
+				parser->error = "Missing ']'";
 				return FALSE;
 			}
 
-			if (data[i] == ']') {
+			if (data[i] == ']')
 				parser->inside_bracket = FALSE;
-			}
 		} else {
 			if (data[i] == '[')
 				parser->inside_bracket = TRUE;
@@ -293,7 +306,7 @@
 		   string always ends with '"', so it's an error if we found
 		   a linebreak.. */
 		if (is_linebreak(data[i])) {
-			parser->error = TRUE;
+			parser->error = "Missing '\"'";
 			return FALSE;
 		}
 	}
@@ -307,7 +320,7 @@
 	if ((parser->flags & IMAP_PARSE_FLAG_LITERAL_SIZE) == 0) {
 		if (parser->literal_size > parser->max_literal_size) {
 			/* too long string, abort. */
-			parser->error = TRUE;
+			parser->error = "Literal size too large";
 			return FALSE;
 		}
 
@@ -337,7 +350,7 @@
 		}
 
 		if (data[i] < '0' || data[i] > '9') {
-			parser->error = TRUE;
+			parser->error = "Invalid literal size";
 			return FALSE;
 		}
 
@@ -346,7 +359,7 @@
 
 		if (parser->literal_size < prev_size) {
 			/* wrapped around, abort. */
-			parser->error = TRUE;
+			parser->error = "Literal size too large";
 			return FALSE;
 		}
 	}
@@ -372,7 +385,7 @@
 		}
 
 		if (*data != '\n') {
-			parser->error = TRUE;
+			parser->error = "Missing LF after literal size";
 			return FALSE;
 		}
 
@@ -499,9 +512,14 @@
 	       IS_UNFINISHED(parser)) {
 		if (!imap_parser_read_arg(parser))
 			break;
+
+		if (parser->element_count > parser->max_elements) {
+			parser->error = "Too many argument elements";
+			break;
+		}
 	}
 
-	if (parser->error) {
+	if (parser->error != NULL) {
 		/* error, abort */
 		*args = NULL;
 		return -1;

Index: imap-parser.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-imap/imap-parser.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- imap-parser.h	6 Dec 2002 01:09:22 -0000	1.5
+++ imap-parser.h	9 Dec 2002 15:25:20 -0000	1.6
@@ -41,16 +41,21 @@
 	ImapArg args[1]; /* variable size */
 };
 
-/* Create new IMAP argument parser. The max. size of input limits the
-   maximum size of each argument. max_literal_size also limits sizes of
-   literals which we even try to handle if FLAG_LITERAL_SIZE is not set.
-   output is used for sending command continuation requests for literals. */
+/* 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. */
 ImapParser *imap_parser_create(IStream *input, OStream *output,
-			       size_t max_literal_size);
+			       size_t max_literal_size, size_t max_elements);
 void imap_parser_destroy(ImapParser *parser);
 
 /* Reset the parser to initial state. */
 void imap_parser_reset(ImapParser *parser);
+
+/* Return the last error in parser. */
+const char *imap_parser_get_error(ImapParser *parser);
 
 /* Read a number of arguments. This function doesn't call i_stream_read(), you
    need to do that. Returns number of arguments read (may be less than count




More information about the dovecot-cvs mailing list