From: Timo Sirainen Date: Fri, 17 Apr 2026 14:55:34 +0000 (+0200) Subject: [PATCH 03/14] imap: Stream ENVELOPE to client without ostream memory duplication X-Git-Tag: archive/raspbian/1%2.4.1+dfsg1-6+rpi1+deb13u7^2~61 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=cf0656349a5dd2e9c22349971a6e3fb2094eef2a;p=dovecot.git [PATCH 03/14] imap: Stream ENVELOPE to client without ostream memory duplication Same fix as for BODYSTRUCTURE: avoid copying the envelope string into the ostream ring buffer by using o_stream_set_max_buffer_size(0) + o_stream_send_istream() with a continuation handler. Co-Authored-By: Claude Sonnet 4.6 Gbp-Pq: Name 0003-imap-Stream-ENVELOPE-to-client-without-ostream-memor.patch --- diff --git a/src/imap/imap-fetch.c b/src/imap/imap-fetch.c index b4a8a46..5a66299 100644 --- a/src/imap/imap-fetch.c +++ b/src/imap/imap-fetch.c @@ -793,6 +793,34 @@ static bool fetch_bodystructure_init(struct imap_fetch_init_context *ctx) return TRUE; } +static int fetch_envelope_stream_continue(struct imap_fetch_context *ctx) +{ + struct imap_fetch_state *state = &ctx->state; + enum ostream_send_istream_result res; + + o_stream_set_max_buffer_size(ctx->client->output, 0); + res = o_stream_send_istream(ctx->client->output, state->cur_input); + o_stream_set_max_buffer_size(ctx->client->output, SIZE_MAX); + + switch (res) { + case OSTREAM_SEND_ISTREAM_RESULT_FINISHED: + i_stream_unref(&state->cur_input); + state->cont_handler = NULL; + if (o_stream_send(ctx->client->output, ")", 1) < 0) + return -1; + return 1; + case OSTREAM_SEND_ISTREAM_RESULT_WAIT_INPUT: + i_unreached(); + case OSTREAM_SEND_ISTREAM_RESULT_WAIT_OUTPUT: + return 0; + case OSTREAM_SEND_ISTREAM_RESULT_ERROR_INPUT: + i_unreached(); + case OSTREAM_SEND_ISTREAM_RESULT_ERROR_OUTPUT: + return -1; + } + i_unreached(); +} + static int fetch_envelope(struct imap_fetch_context *ctx, struct mail *mail, void *context ATTR_UNUSED) { @@ -808,11 +836,13 @@ static int fetch_envelope(struct imap_fetch_context *ctx, struct mail *mail, return -1; } - if (o_stream_send(ctx->client->output, "ENVELOPE (", 10) < 0 || - o_stream_send_str(ctx->client->output, envelope) < 0 || - o_stream_send(ctx->client->output, ")", 1) < 0) + if (o_stream_send(ctx->client->output, "ENVELOPE (", 10) < 0) return -1; - return 1; + + ctx->state.cur_input = + i_stream_create_from_data(envelope, strlen(envelope)); + ctx->state.cont_handler = fetch_envelope_stream_continue; + return fetch_envelope_stream_continue(ctx); } static bool fetch_envelope_init(struct imap_fetch_init_context *ctx)