]> dgit.raspbian.org Git - dovecot.git/commitdiff
[PATCH 08/14] lib-mail: Make istream-header-filter's per-header size limit configurable
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Sun, 19 Apr 2026 15:15:49 +0000 (18:15 +0300)
committerNoah Meyerhans <noahm@debian.org>
Wed, 16 Sep 2026 19:06:35 +0000 (15:06 -0400)
Until now the internal message_header_parser_ctx used the default
MESSAGE_HEADER_BLOCK_DEFAULT_MAX_SIZE (10 MB) cap. In practice that cap
only bounded hdr->full_value; per-chunk hdr->value was delivered in full
regardless. A subsequent change to message_parse_header_next() will
clamp hdr->value cumulatively as well, and at that point the 10 MB
default would silently truncate data for callers like mbox-save that
stream raw header bytes to storage.

Default the filter to SIZE_MAX (unlimited) to preserve the effective
behavior and add i_stream_header_filter_set_max_header_block_size() so
callers that genuinely want a cap (index_mail_get_header_stream()) can
opt in.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Gbp-Pq: Name 0008-lib-mail-Make-istream-header-filter-s-per-header-siz.patch

src/lib-mail/istream-header-filter.c
src/lib-mail/istream-header-filter.h

index 0ec6cb1d08c88e6f306a96ef225142ee57c839d3..81842630396b767b52769c0a7f7f4f22e075a12a 100644 (file)
@@ -29,6 +29,7 @@ struct header_filter_istream {
        buffer_t *hdr_buf;
        int snapshot_pending_refcount;
        struct message_size header_size;
+       size_t max_header_block_size;
        uoff_t skip_count;
        uoff_t last_lf_offset;
 
@@ -194,6 +195,8 @@ static ssize_t read_header(struct header_filter_istream *mstream)
                mstream->hdr_ctx =
                        message_parse_header_init(mstream->istream.parent,
                                                  NULL, 0);
+               message_parse_header_set_limit(mstream->hdr_ctx,
+                                              mstream->max_header_block_size);
        }
 
        /* remove skipped data from hdr_buf */
@@ -709,6 +712,9 @@ i_stream_create_header_filter(struct istream *input,
        mstream->pool = pool_alloconly_create(MEMPOOL_GROWING
                                              "header filter stream", 256);
        mstream->istream.max_buffer_size = input->real_stream->max_buffer_size;
+       /* Default to no per-header block size limit. Callers that want one
+          call i_stream_header_filter_set_max_header_block_size(). */
+       mstream->max_header_block_size = SIZE_MAX;
 
        mstream->headers = headers_count == 0 ? NULL :
                p_new(mstream->pool, const char *, headers_count);
@@ -762,3 +768,17 @@ void i_stream_header_filter_add(struct header_filter_istream *input,
        buffer_append(input->hdr_buf, data, size);
        input->headers_edited = TRUE;
 }
+
+void i_stream_header_filter_set_max_header_block_size(
+       struct istream *input, size_t max_header_block_size)
+{
+       struct header_filter_istream *mstream =
+               container_of(input->real_stream, struct header_filter_istream,
+                            istream);
+
+       mstream->max_header_block_size = max_header_block_size;
+       if (mstream->hdr_ctx != NULL) {
+               message_parse_header_set_limit(mstream->hdr_ctx,
+                                              max_header_block_size);
+       }
+}
index 7c5ca3652ba4e441d2967b03ab5b11e735c7ba72..6a2ffd89414be362d4907839ee72c1c11a19a6d1 100644 (file)
@@ -49,4 +49,12 @@ i_stream_create_header_filter(struct istream *input,
 void i_stream_header_filter_add(struct header_filter_istream *input,
                                const void *data, size_t size);
 
+/* Set a per-header-block maximum size for this filter stream. Data beyond
+   this limit in any single header is dropped from the filter's output and
+   from values delivered to the filter callback. The default is SIZE_MAX
+   (unlimited). Use MESSAGE_HEADER_BLOCK_DEFAULT_MAX_SIZE from
+   message-header-parser.h for the standard cap. */
+void i_stream_header_filter_set_max_header_block_size(
+       struct istream *input, size_t max_header_block_size);
+
 #endif