From: Timo Sirainen Date: Fri, 8 Nov 2019 08:57:01 +0000 (+0200) Subject: lib-imap: Add IMAP_ARG_EOL parameter also for unfinished lists X-Git-Tag: 2.3.9~56 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=32804e656ff8e8e31ead060ff9c9e1da86c89066;p=thirdparty%2Fdovecot%2Fcore.git lib-imap: Add IMAP_ARG_EOL parameter also for unfinished lists If list parsing was stopped due to IMAP_ARG_LITERAL_SIZE* the list didn't have IMAP_ARG_EOL added. However, imap_arg_get_list() could still have been used for it, which assumes that the IMAP_ARG_EOL exists. This didn't seem to cause any actual bugs so far, but the following commits require this. The IMAP_ARG_EOL is appended and deleted immediately. This way it's seen by imap_arg_get_list(), but it won't change any other behavior unexpectedly. --- diff --git a/src/lib-imap/imap-arg.c b/src/lib-imap/imap-arg.c index fcfea5f831..3011b5fd00 100644 --- a/src/lib-imap/imap-arg.c +++ b/src/lib-imap/imap-arg.c @@ -79,9 +79,14 @@ bool imap_arg_get_list_full(const struct imap_arg *arg, *list_r = array_get(&arg->_data.list, &count); - /* drop IMAP_ARG_EOL from list size */ - i_assert(count > 0); - *list_count_r = count - 1; + if (count > 0 && (*list_r)[count-1].type == IMAP_ARG_EOL) + count--; + else { + /* imap-parser stopped early (e.g. due to reading literal size). + The IMAP_ARG_EOL was added to the list only temporarily. */ + i_assert((*list_r)[count].type == IMAP_ARG_EOL); + } + *list_count_r = count; return TRUE; } diff --git a/src/lib-imap/imap-parser.c b/src/lib-imap/imap-parser.c index 7f58d99e2f..238d2efa0a 100644 --- a/src/lib-imap/imap-parser.c +++ b/src/lib-imap/imap-parser.c @@ -759,12 +759,18 @@ static int finish_line(struct imap_parser *parser, unsigned int count, parser->cur_pos = 0; parser->cur_resp_text = FALSE; - if (parser->list_arg != NULL && !parser->literal_size_return && - (parser->flags & IMAP_PARSE_FLAG_STOP_AT_LIST) == 0) { + if (parser->list_arg == NULL) { + /* no open list */ + } else if (!parser->literal_size_return && + (parser->flags & IMAP_PARSE_FLAG_STOP_AT_LIST) == 0) { parser->error = IMAP_PARSE_ERROR_BAD_SYNTAX; parser->error_msg = "Missing ')'"; *args_r = NULL; return -1; + } else { + arg = array_append_space(&parser->list_arg->_data.list); + arg->type = IMAP_ARG_EOL; + array_pop_back(&parser->list_arg->_data.list); } arg = array_append_space(&parser->root_list); @@ -775,6 +781,12 @@ static int finish_line(struct imap_parser *parser, unsigned int count, return ret; } +static void imap_parser_delete_extra_eol(struct imap_parser *parser) +{ + array_pop_back(&parser->root_list); + parser->args_added_extra_eol = FALSE; +} + int imap_parser_read_args(struct imap_parser *parser, unsigned int count, enum imap_parser_flags flags, const struct imap_arg **args_r) @@ -783,8 +795,7 @@ int imap_parser_read_args(struct imap_parser *parser, unsigned int count, if (parser->args_added_extra_eol) { /* delete EOL */ - array_pop_back(&parser->root_list); - parser->args_added_extra_eol = FALSE; + imap_parser_delete_extra_eol(parser); parser->literal_size_return = FALSE; } @@ -866,6 +877,7 @@ void imap_parser_read_last_literal(struct imap_parser *parser) struct imap_arg *last_arg; i_assert(parser->literal_size_return); + i_assert(parser->args_added_extra_eol); last_arg = imap_parser_get_last_literal_size(parser, &list); i_assert(last_arg != NULL); @@ -874,8 +886,7 @@ void imap_parser_read_last_literal(struct imap_parser *parser) i_assert(parser->literal_size == last_arg->_data.literal_size); /* delete EOL */ - array_pop_back(&parser->root_list); - parser->args_added_extra_eol = FALSE; + imap_parser_delete_extra_eol(parser); /* delete literal size */ array_pop_back(list);