From cbc1c48990dbcd3b6a366a1cbb4c74ee55f9c8a8 Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan.bosch@open-xchange.com> Date: Thu, 4 Nov 2021 10:46:57 +0100 Subject: [PATCH] lib-sieve: util: edit-mail - Fix returning buffer-full condition when data was read. Fixes: Panic: file istream-crlf.c: line 24 (i_stream_crlf_read_common): assertion failed: (ret != -2) Panic: file istream.h: line 228 (i_stream_read_more): assertion failed: (ret != -2) (various other similar panics are possible) --- src/lib-sieve/util/edit-mail.c | 7 ++- src/lib-sieve/util/test-edit-mail.c | 70 +++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 2 deletions(-) diff --git a/src/lib-sieve/util/edit-mail.c b/src/lib-sieve/util/edit-mail.c index 3382b7a71..5034e5803 100644 --- a/src/lib-sieve/util/edit-mail.c +++ b/src/lib-sieve/util/edit-mail.c @@ -1915,8 +1915,11 @@ static ssize_t merge_modified_headers(struct edit_mail_istream *edstream) size = edstream->cur_header->field->size - appended; if (size > 0) { /* Determine how much we can write */ - if (!i_stream_try_alloc(stream, size, &avail)) - return -2; + if (!i_stream_try_alloc(stream, size, &avail)) { + if (written == 0) + return -2; + break; + } wsize = (size >= avail ? avail : size); /* Write (part of) the header to buffer */ diff --git a/src/lib-sieve/util/test-edit-mail.c b/src/lib-sieve/util/test-edit-mail.c index 244e6b2bd..0e263a2c2 100644 --- a/src/lib-sieve/util/test-edit-mail.c +++ b/src/lib-sieve/util/test-edit-mail.c @@ -740,11 +740,81 @@ static void test_edit_mail_big_header(void) test_end(); } +static void test_edit_mail_small_buffer(void) +{ + static const char *message = + "X-A: AAAA\n" + "X-B: BBBB\n" + "\n" + "Frop!\n"; + struct istream *input_msg, *input_mail; + buffer_t *buffer; + struct mail_raw *rawmail; + struct edit_mail *edmail; + struct mail *mail; + const char *value; + unsigned int i; + + test_begin("edit-mail - small buffer"); + test_init(); + + /* compose the message */ + + input_msg = i_stream_create_from_data(message, strlen(message)); + i_stream_set_max_buffer_size(input_msg, 16); + + rawmail = mail_raw_open_stream(test_raw_mail_user, input_msg); + + edmail = edit_mail_wrap(rawmail->mail); + + /* add headers */ + + for (i = 0; i < 16; i++) { + edit_mail_header_add(edmail, "X-F", "FF", FALSE); + edit_mail_header_add(edmail, "X-L", "LL", TRUE); + } + + mail = edit_mail_get_mail(edmail); + + /* prepare tests */ + + if (mail_get_stream(mail, NULL, NULL, &input_mail) < 0) { + i_fatal("Failed to open mail stream: %s", + mailbox_get_last_internal_error(mail->box, NULL)); + } + + buffer = buffer_create_dynamic(default_pool, 1024); + + /* evaluate modified header */ + + test_assert(mail_get_first_header_utf8(mail, "X-F", &value) > 0); + test_assert(mail_get_first_header_utf8(mail, "X-A", &value) > 0); + test_assert(mail_get_first_header_utf8(mail, "X-B", &value) > 0); + test_assert(mail_get_first_header_utf8(mail, "X-L", &value) > 0); + + /* check stream read */ + + i_stream_seek(input_mail, 0); + buffer_set_used_size(buffer, 0); + + test_stream_data(input_mail, buffer); + + /* clean up */ + + buffer_free(&buffer); + edit_mail_unwrap(&edmail); + mail_raw_close(&rawmail); + i_stream_unref(&input_msg); + test_deinit(); + test_end(); +} + int main(int argc, char *argv[]) { static void (*test_functions[])(void) = { test_edit_mail_concatenated, test_edit_mail_big_header, + test_edit_mail_small_buffer, NULL }; const enum master_service_flags service_flags = -- GitLab