]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib, global: i_stream_create_chain() - Add max_buffer_size
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 28 Sep 2021 15:13:12 +0000 (18:13 +0300)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Mon, 11 Oct 2021 05:24:23 +0000 (05:24 +0000)
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.

src/imap/cmd-append.c
src/lib-http/test-http-client-errors.c
src/lib-smtp/smtp-server-cmd-data.c
src/lib-storage/index/pop3c/pop3c-client.c
src/lib/istream-chain.c
src/lib/istream-chain.h
src/lib/test-istream-chain.c

index 72f078a4959474a892d1e381acb973958356c63e..0d0c1c3b569d3f211bd032c5a11e3ee40f84f612 100644 (file)
@@ -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 */
index 4dc558ac88eaa54c6ca422153b75f2da5532f8e8..e127041d642c576efbef3d92e115846bd6549438 100644 (file)
@@ -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));
index 65b52ec78e9ecd4632c49611574ceea942ed1ece..7f33fdfc149c099fa18a21367944822efc4e8cba 100644 (file)
@@ -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);
        }
 }
 
index df0bc6d79514d89a9f86bff5e6cbf9f65983d090..44544a350f5e1d4aabf6b20b96692b6407a484f8 100644 (file)
@@ -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,
index a69122d35875d8fb96d19f37c3e8861ce904b973..3b9a87b62b34e21f92e5ab3c8859534f12437d75 100644 (file)
@@ -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;
index 5dee53b7c04fcb98f7c9fb002b7821e1cad0a6e9..e5ba68be3248e0e448d24bb42b35cd74315c5033 100644 (file)
@@ -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);
index 3307ddcdf3d22d81faf940ec01e428eb8ec822ca..cb72c6457d576c967e6953efe15b465b0123c450 100644 (file)
@@ -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);