]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage, imapc: Fix caching headers as empty values when handling partial header...
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 21 Oct 2025 20:45:45 +0000 (23:45 +0300)
committerTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 21 Oct 2025 20:50:53 +0000 (23:50 +0300)
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.

src/lib-storage/index/imapc/imapc-mail-fetch.c
src/lib-storage/index/index-mail-headers.c
src/lib-storage/index/index-mail.h
src/lib-storage/index/index-search.c

index 71d636f5187cb0e349e9d246050434dd2879f5fe..4e6447a97bf730f9d275f9417cca4fbc5530baf4 100644 (file)
@@ -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 {
index 18c922239daa154cf682b035926334f1362e300c..b5a20edc8a88205422e3af89b8cbb968f3c81f14 100644 (file)
@@ -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 |
index 9e2159898e9820bc079f473016b19b401ec4e826..4e0301f5a535b7402b4850ad83883af3c1dd81c1 100644 (file)
@@ -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,
index 42646e59d521bd010f2f268c374ad2f2f60b560c..c8124af6b8b1830ed5eabf88db8b63ae5a383911 100644 (file)
@@ -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);