From: Timo Sirainen Date: Tue, 28 Sep 2021 15:13:12 +0000 (+0300) Subject: lib, global: i_stream_create_chain() - Add max_buffer_size X-Git-Tag: 2.3.18~210 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b4217b8d36836d77277487126ead4085ba328d54;p=thirdparty%2Fdovecot%2Fcore.git lib, global: i_stream_create_chain() - Add max_buffer_size This makes sure that the istream size can't grow too large and waste memory. Previously the istream max_buffer_size was dynamically changed to be the smallest seen max_buffer_size in chained istreams. This mostly worked, but sometimes the istream-chain's max_buffer_size was requested before even the first istream was added to it. Having an explicit max_buffer_size avoids all the problems of it being dynamic, and there's not really any need for it anyway. --- diff --git a/src/imap/cmd-append.c b/src/imap/cmd-append.c index 72f078a495..0d0c1c3b56 100644 --- a/src/imap/cmd-append.c +++ b/src/imap/cmd-append.c @@ -569,8 +569,8 @@ cmd_append_handle_args(struct client_command_context *cmd, if (cat_list != NULL) { ctx->cat_msg_size = 0; - ctx->input = i_stream_create_chain(&ctx->catchain); - i_stream_set_max_buffer_size(ctx->input, IO_BLOCK_SIZE); + ctx->input = i_stream_create_chain(&ctx->catchain, + IO_BLOCK_SIZE); } else { if (ctx->literal_size == 0) { /* no message data, abort */ diff --git a/src/lib-http/test-http-client-errors.c b/src/lib-http/test-http-client-errors.c index 4dc558ac88..e127041d64 100644 --- a/src/lib-http/test-http-client-errors.c +++ b/src/lib-http/test-http-client-errors.c @@ -1608,7 +1608,7 @@ test_client_early_success(const struct http_client_settings *client_set) "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\r\n"); } - chain_input = i_stream_create_chain(&chain); + chain_input = i_stream_create_chain(&chain, IO_BLOCK_SIZE); input = i_stream_create_copy_from_data(str_data(payload), str_len(payload)); diff --git a/src/lib-smtp/smtp-server-cmd-data.c b/src/lib-smtp/smtp-server-cmd-data.c index 65b52ec78e..7f33fdfc14 100644 --- a/src/lib-smtp/smtp-server-cmd-data.c +++ b/src/lib-smtp/smtp-server-cmd-data.c @@ -564,7 +564,8 @@ void smtp_server_connection_data_chunk_init(struct smtp_server_cmd_ctx *cmd) i_assert(data_cmd->chunk_first); i_assert(conn->state.data_chain_input == NULL); conn->state.data_chain_input = - i_stream_create_chain(&conn->state.data_chain); + i_stream_create_chain(&conn->state.data_chain, + IO_BLOCK_SIZE); } } diff --git a/src/lib-storage/index/pop3c/pop3c-client.c b/src/lib-storage/index/pop3c/pop3c-client.c index df0bc6d795..44544a350f 100644 --- a/src/lib-storage/index/pop3c/pop3c-client.c +++ b/src/lib-storage/index/pop3c/pop3c-client.c @@ -889,7 +889,7 @@ pop3c_client_cmd_stream_async(struct pop3c_client *client, const char *cmdline, cmd = pop3c_client_cmd_line_async(client, cmdline, callback, context); - input = i_stream_create_chain(&cmd->chain); + input = i_stream_create_chain(&cmd->chain, POP3C_MAX_INBUF_SIZE); inputs[0] = i_stream_create_dot(input, TRUE); inputs[1] = NULL; cmd->input = i_stream_create_seekable(inputs, POP3C_MAX_INBUF_SIZE, diff --git a/src/lib/istream-chain.c b/src/lib/istream-chain.c index a69122d358..3b9a87b62b 100644 --- a/src/lib/istream-chain.c +++ b/src/lib/istream-chain.c @@ -29,7 +29,6 @@ struct chain_istream { the beginning of the current link's stream. */ size_t prev_stream_left; size_t prev_skip; - bool have_explicit_max_buffer_size; struct istream_chain chain; }; @@ -51,17 +50,8 @@ i_stream_chain_append_internal(struct istream_chain *chain, i_stream_ref(stream); if (chain->head == NULL && stream != NULL) { - struct chain_istream *cstream = chain->stream; - - if (cstream->have_explicit_max_buffer_size) { - i_stream_set_max_buffer_size(stream, - chain->stream->istream.max_buffer_size); - } else { - size_t max_size = i_stream_get_max_buffer_size(stream); - - if (cstream->istream.max_buffer_size < max_size) - cstream->istream.max_buffer_size = max_size; - } + i_stream_set_max_buffer_size(stream, + chain->stream->istream.max_buffer_size); } DLLIST2_APPEND(&chain->head, &chain->tail, link); /* if io_add_istream() has been added to this chain stream, notify @@ -88,7 +78,6 @@ i_stream_chain_set_max_buffer_size(struct iostream_private *stream, container_of(stream, struct chain_istream, istream.iostream); struct istream_chain_link *link = cstream->chain.head; - cstream->have_explicit_max_buffer_size = TRUE; cstream->istream.max_buffer_size = max_size; while (link != NULL) { if (link->stream != NULL) @@ -334,12 +323,14 @@ i_stream_chain_snapshot(struct istream_private *stream, return snapshot; } -struct istream *i_stream_create_chain(struct istream_chain **chain_r) +struct istream *i_stream_create_chain(struct istream_chain **chain_r, + size_t max_buffer_size) { struct chain_istream *cstream; cstream = i_new(struct chain_istream, 1); cstream->chain.stream = cstream; + cstream->istream.max_buffer_size = max_buffer_size; cstream->istream.iostream.close = i_stream_chain_close; cstream->istream.iostream.destroy = i_stream_chain_destroy; diff --git a/src/lib/istream-chain.h b/src/lib/istream-chain.h index 5dee53b7c0..e5ba68be32 100644 --- a/src/lib/istream-chain.h +++ b/src/lib/istream-chain.h @@ -9,7 +9,8 @@ struct istream_chain; NULL. Streams that were finished to EOF are unreferenced. The chain stream is obviously not seekable and it has no determinable size. The chain_r argument returns a pointer to the chain object. */ -struct istream *i_stream_create_chain(struct istream_chain **chain_r); +struct istream *i_stream_create_chain(struct istream_chain **chain_r, + size_t max_buffer_size); /* Append an input stream to the chain. */ void i_stream_chain_append(struct istream_chain *chain, struct istream *stream); diff --git a/src/lib/test-istream-chain.c b/src/lib/test-istream-chain.c index 3307ddcdf3..cb72c6457d 100644 --- a/src/lib/test-istream-chain.c +++ b/src/lib/test-istream-chain.c @@ -16,7 +16,7 @@ static void test_istream_chain_basic(void) test_input = test_istream_create("stream1"); test_input2 = test_istream_create("STREAM2"); - input = i_stream_create_chain(&chain); + input = i_stream_create_chain(&chain, IO_BLOCK_SIZE); /* no input */ test_assert(i_stream_read(input) == 0); /* stream1 input */ @@ -63,7 +63,7 @@ static void test_istream_chain_early_end(void) test_istream_set_size(test_input, 3); test_istream_set_allow_eof(test_input, FALSE); - input = i_stream_create_chain(&chain); + input = i_stream_create_chain(&chain, IO_BLOCK_SIZE); i_stream_chain_append(chain, test_input); test_assert(i_stream_read(input) == 3); test_istream_set_size(test_input, 5); @@ -96,7 +96,7 @@ static void test_istream_chain_accumulate(void) test_istreams[3] = test_istream_create("z1y2x3w4v5u6t7s8r9q0p.o,n"); test_istreams[4] = test_istream_create("aAbBcCdDeEfFgGhHiIjJ"); - input = i_stream_create_chain(&chain); + input = i_stream_create_chain(&chain, IO_BLOCK_SIZE); /* no input */ test_assert(i_stream_read(input) == 0);