From: Timo Sirainen Date: Mon, 27 Apr 2026 14:40:46 +0000 (+0300) Subject: [PATCH] lib-imap: Fix imap_parser_params.list_count_limit to actually work X-Git-Tag: archive/raspbian/1%2.4.1+dfsg1-6+rpi1+deb13u6^2~1 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=626570a567cc9a0fcead482adaabe84a1f1bbffb;p=dovecot.git [PATCH] lib-imap: Fix imap_parser_params.list_count_limit to actually work The previous fix in d0f67b52914565a35f3817335ab9633cb291513c was accidentally limiting the number of ')', not the number of '('. Gbp-Pq: Name CVE-2026-42006.patch --- diff --git a/src/lib-imap/imap-parser.c b/src/lib-imap/imap-parser.c index 6212aed..b1df3d7 100644 --- a/src/lib-imap/imap-parser.c +++ b/src/lib-imap/imap-parser.c @@ -191,8 +191,15 @@ static struct imap_arg *imap_arg_create(struct imap_parser *parser) return arg; } -static void imap_parser_open_list(struct imap_parser *parser) +static bool imap_parser_open_list(struct imap_parser *parser) { + if (parser->list_count >= parser->list_count_limit) { + parser->error_msg = "Too many '('"; + parser->error = IMAP_PARSE_ERROR_BAD_SYNTAX; + return FALSE; + } + parser->list_count++; + parser->list_arg = imap_arg_create(parser); parser->list_arg->type = IMAP_ARG_LIST; p_array_init(&parser->list_arg->_data.list, parser->pool, @@ -200,6 +207,7 @@ static void imap_parser_open_list(struct imap_parser *parser) parser->cur_list = &parser->list_arg->_data.list; parser->cur_type = ARG_PARSE_NONE; + return TRUE; } static bool imap_parser_close_list(struct imap_parser *parser) @@ -217,12 +225,6 @@ static bool imap_parser_close_list(struct imap_parser *parser) parser->error = IMAP_PARSE_ERROR_BAD_SYNTAX; return FALSE; } - if (parser->list_count >= parser->list_count_limit) { - parser->error_msg = "Too many '('"; - parser->error = IMAP_PARSE_ERROR_BAD_SYNTAX; - return FALSE; - } - parser->list_count++; arg = imap_arg_create(parser); arg->type = IMAP_ARG_EOL; @@ -673,7 +675,8 @@ static bool imap_parser_read_arg(struct imap_parser *parser) parser->literal8 = FALSE; break; case '(': - imap_parser_open_list(parser); + if (!imap_parser_open_list(parser)) + return FALSE; if ((parser->flags & IMAP_PARSE_FLAG_STOP_AT_LIST) != 0) { i_stream_skip(parser->input, 1); return FALSE; diff --git a/src/lib-imap/test-imap-parser.c b/src/lib-imap/test-imap-parser.c index 0075de7..e61a1d5 100644 --- a/src/lib-imap/test-imap-parser.c +++ b/src/lib-imap/test-imap-parser.c @@ -85,9 +85,15 @@ static void test_imap_parser_list_limit(void) struct { const char *input; int ret; + const char *error; } tests[] = { - { "(())\r\n", 1 }, - { "((()))\r\n", -1 }, + { "(())\r\n", 1, NULL }, + { "((\r\n", -1, "Missing ')'" }, + { "(()\r\n", -1, "Missing ')'" }, + { "(()))\r\n", -1, "Unexpected ')'" }, + { "((()))\r\n", -1, "Too many '('" }, + { "(({10}\r\n", -2, NULL }, + { "((({10}\r\n", -1, "Too many '('" }, }; struct istream_chain *chain; struct istream *chain_input; @@ -112,6 +118,10 @@ static void test_imap_parser_list_limit(void) (void)i_stream_read(chain_input); test_assert_cmp(imap_parser_read_args(parser, 0, 0, &args), ==, tests[i].ret); + if (tests[i].ret == -1) { + enum imap_parser_error err; + test_assert_strcmp_idx(imap_parser_get_error(parser, &err), tests[i].error, i); + } /* skip over CRLF */ i_stream_skip(chain_input, i_stream_get_data_size(chain_input));