From: Timo Sirainen Date: Tue, 21 Oct 2025 20:45:45 +0000 (+0300) Subject: lib-storage, imapc: Fix caching headers as empty values when handling partial header... X-Git-Tag: 2.4.2~29 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bb1b51d86af68af0be2460cac6f94f3a245b2952;p=thirdparty%2Fdovecot%2Fcore.git lib-storage, imapc: Fix caching headers as empty values when handling partial header fetches When imapc does FETCH BODY.PEEK[HEADER.FIELDS (a b)], the result is valid only for headers "a" and "b". The header parsing was expecting that it was seeing the full header, so if caching decisions had remembered that also header "c" is wanted to be cached, it was done with an empty value. --- diff --git a/src/lib-storage/index/imapc/imapc-mail-fetch.c b/src/lib-storage/index/imapc/imapc-mail-fetch.c index 71d636f518..4e6447a97b 100644 --- a/src/lib-storage/index/imapc/imapc-mail-fetch.c +++ b/src/lib-storage/index/imapc/imapc-mail-fetch.c @@ -773,7 +773,7 @@ imapc_fetch_header_stream(struct imapc_mail *mail, headers_ctx = mailbox_header_lookup_init(mail->imail.mail.mail.box, array_front(&hdr_arr)); - index_mail_parse_header_init(&mail->imail, headers_ctx); + index_mail_parse_header_init(&mail->imail, headers_ctx, FALSE); parser = message_parse_header_init(input, NULL, hdr_parser_flags); while ((ret = message_parse_header_next(parser, &hdr)) > 0) T_BEGIN { diff --git a/src/lib-storage/index/index-mail-headers.c b/src/lib-storage/index/index-mail-headers.c index 18c922239d..b5a20edc8a 100644 --- a/src/lib-storage/index/index-mail-headers.c +++ b/src/lib-storage/index/index-mail-headers.c @@ -200,7 +200,8 @@ static void index_mail_parse_header_register_all_wanted(struct index_mail *mail) } void index_mail_parse_header_init(struct index_mail *mail, - struct mailbox_header_lookup_ctx *headers) + struct mailbox_header_lookup_ctx *headers, + bool full_header_stream) { struct index_mail_data *data = &mail->data; const uint8_t *match; @@ -239,6 +240,18 @@ void index_mail_parse_header_init(struct index_mail *mail, } } + mail->data.header_parser_initialized = TRUE; + mail->data.parse_line_num = 0; + i_zero(&mail->data.parse_line); + + if (!full_header_stream) { + /* Input stream contains only the specified headers. Don't + initialize any other header matches, because they won't be + in the input. */ + i_assert(headers != NULL && headers->count > 0); + return; + } + if (data->wanted_headers != NULL && data->wanted_headers != headers) { headers = data->wanted_headers; for (i = 0; i < headers->count; i++) { @@ -268,9 +281,6 @@ void index_mail_parse_header_init(struct index_mail *mail, array_idx_set(&mail->header_match, field_idx, &mail->header_match_value); } - mail->data.header_parser_initialized = TRUE; - mail->data.parse_line_num = 0; - i_zero(&mail->data.parse_line); } static void index_mail_parse_finish_imap_envelope(struct index_mail *mail) @@ -408,7 +418,7 @@ index_mail_cache_parse_init(struct mail *_mail, struct istream *input) input = tee_i_stream_create_child(mail->data.tee_stream); input2 = tee_i_stream_create_child(mail->data.tee_stream); - index_mail_parse_header_init(mail, NULL); + index_mail_parse_header_init(mail, NULL, TRUE); mail->data.parser_input = input; mail->data.parser_ctx = message_parser_init(mail->mail.data_pool, input, @@ -459,7 +469,7 @@ int index_mail_parse_headers_internal(struct index_mail *mail, i_assert(data->stream != NULL); - index_mail_parse_header_init(mail, headers); + index_mail_parse_header_init(mail, headers, TRUE); if (data->parts == NULL || data->save_bodystructure_header || (data->access_part & PARSE_BODY) != 0) { @@ -984,7 +994,7 @@ int index_mail_get_header_stream(struct mail *_mail, if (mail_get_hdr_stream_because(_mail, NULL, reason, &input) < 0) return -1; - index_mail_parse_header_init(mail, headers); + index_mail_parse_header_init(mail, headers, TRUE); mail->data.filter_stream = i_stream_create_header_filter(mail->data.stream, HEADER_FILTER_INCLUDE | diff --git a/src/lib-storage/index/index-mail.h b/src/lib-storage/index/index-mail.h index 9e2159898e..4e0301f5a5 100644 --- a/src/lib-storage/index/index-mail.h +++ b/src/lib-storage/index/index-mail.h @@ -191,7 +191,8 @@ void index_mail_set_message_parts_corrupted(struct mail *mail, const char *error bool index_mail_want_parse_headers(struct index_mail *mail); void index_mail_parse_header_init(struct index_mail *mail, - struct mailbox_header_lookup_ctx *headers) + struct mailbox_header_lookup_ctx *headers, + bool full_header_stream) ATTR_NULL(2); void index_mail_parse_header(struct message_part *part, struct message_header_line *hdr, diff --git a/src/lib-storage/index/index-search.c b/src/lib-storage/index/index-search.c index 42646e59d5..c8124af6b8 100644 --- a/src/lib-storage/index/index-search.c +++ b/src/lib-storage/index/index-search.c @@ -814,7 +814,7 @@ static int search_arg_match_text(struct mail_search_arg *args, index_mail_want_parse_headers(hdr_ctx.imail); if (hdr_ctx.parse_headers) { index_mail_parse_header_init(hdr_ctx.imail, - headers_ctx); + headers_ctx, TRUE); } message_parse_header(input, NULL, hdr_parser_flags, search_header, &hdr_ctx);