From: Timo Sirainen Date: Sun, 19 Apr 2026 15:15:49 +0000 (+0300) Subject: [PATCH 08/14] lib-mail: Make istream-header-filter's per-header size limit configurable X-Git-Tag: archive/raspbian/1%2.4.1+dfsg1-6+rpi1+deb13u7^2~56 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=c4ad54206d2b72b274c64056c5882314cc8f3ee3;p=dovecot.git [PATCH 08/14] lib-mail: Make istream-header-filter's per-header size limit configurable 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) Gbp-Pq: Name 0008-lib-mail-Make-istream-header-filter-s-per-header-siz.patch --- diff --git a/src/lib-mail/istream-header-filter.c b/src/lib-mail/istream-header-filter.c index 0ec6cb1..8184263 100644 --- a/src/lib-mail/istream-header-filter.c +++ b/src/lib-mail/istream-header-filter.c @@ -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); + } +} diff --git a/src/lib-mail/istream-header-filter.h b/src/lib-mail/istream-header-filter.h index 7c5ca36..6a2ffd8 100644 --- a/src/lib-mail/istream-header-filter.h +++ b/src/lib-mail/istream-header-filter.h @@ -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