# HG changeset patch # User Timo Sirainen # Date 1453121865 -7200 # Node ID f9d75e6e16184f4bc2c25b9b37712421fda10726 # Parent 796996d66955ed9e3cbcb8785a3baf36a412c004 lib-mail: istream-binary-converter lost last few chars from root-level binary content. diff -r 796996d66955 -r f9d75e6e1618 src/lib-mail/istream-binary-converter.c --- a/src/lib-mail/istream-binary-converter.c Mon Jan 18 14:56:47 2016 +0200 +++ b/src/lib-mail/istream-binary-converter.c Mon Jan 18 14:57:45 2016 +0200 @@ -182,10 +182,19 @@ if (stream->pos - stream->skip >= stream->max_buffer_size) return -2; + old_size = stream->pos - stream->skip; switch (message_parser_parse_next_block(bstream->parser, &block)) { case -1: /* done / error */ + if (bstream->convert_part != NULL && + bstream->base64_delayed_len > 0) { + /* flush any pending base64 output */ + stream_encode_base64(bstream, "", 0); + new_size = stream->pos - stream->skip; + i_assert(old_size != new_size); + return new_size - old_size; + } stream->istream.eof = TRUE; stream->istream.stream_errno = stream->parent->stream_errno; return -1; @@ -196,8 +205,6 @@ break; } - old_size = stream->pos - stream->skip; - if (block.part != bstream->convert_part && bstream->convert_part != NULL) { /* end of base64 encoded part */ diff -r 796996d66955 -r f9d75e6e1618 src/lib-mail/test-istream-binary-converter.c --- a/src/lib-mail/test-istream-binary-converter.c Mon Jan 18 14:56:47 2016 +0200 +++ b/src/lib-mail/test-istream-binary-converter.c Mon Jan 18 14:57:45 2016 +0200 @@ -1,6 +1,8 @@ /* Copyright (c) 2007-2016 Dovecot authors, see the included COPYING file */ #include "lib.h" +#include "base64.h" +#include "buffer.h" #include "str.h" #include "sha1.h" #include "istream.h" @@ -21,7 +23,7 @@ #define BINARY_TEXT_SHORT "eh" #define BINARY_TEXT_SHORT_BASE64 "ZWg=" -static const char mail_input[] = +static const char mail_input_mime[] = "MIME-Version: 1.0\r\n" "Content-Type: multipart/alternative;\r\n boundary=\"bound\"\r\n" "\r\n" @@ -36,13 +38,13 @@ "Content-Transfer-Encoding: binary\r\n" "\r\n" BINARY_TEXT_SHORT -"\r\n--bound\r\n" +"\n--bound\r\n" "Content-Type: text/plain\r\n" "\r\n" "hello world\r\n" "\r\n--bound--\r\n"; -static const char mail_output[] = +static const char mail_output_mime[] = "MIME-Version: 1.0\r\n" "Content-Type: multipart/alternative;\r\n boundary=\"bound\"\r\n" "\r\n" @@ -57,38 +59,97 @@ "Content-Transfer-Encoding: base64\r\n" "\r\n" BINARY_TEXT_SHORT_BASE64 -"\r\n--bound\r\n" +"\n--bound\r\n" "Content-Type: text/plain\r\n" "\r\n" "hello world\r\n" "\r\n--bound--\r\n"; -static void test_istream_binary_converter(void) +static const char mail_input_root_hdr[] = +"MIME-Version: 1.0\r\n" +"Content-Transfer-Encoding: binary\r\n" +"Content-Type: text/plain\r\n" +"\r\n"; + +static const char mail_output_root_hdr[] = +"MIME-Version: 1.0\r\n" +"Content-Transfer-Encoding: base64\r\n" +"Content-Type: text/plain\r\n" +"\r\n"; + +static const char mail_root_nonbinary[] = +"MIME-Version: 1.0\r\n" +"Content-Type: text/plain\r\n" +"\r\n" +"hello\n\n"; + +static void +test_istream_binary_converter_test(const char *mail_input, unsigned int mail_input_len, + const char *mail_output, unsigned int mail_output_len, + unsigned int idx) { struct istream *datainput, *input; const unsigned char *data; size_t i, size; int ret; - test_begin("istream binary converter"); - datainput = test_istream_create_data(mail_input, sizeof(mail_input)); + datainput = test_istream_create_data(mail_input, mail_input_len); test_istream_set_allow_eof(datainput, FALSE); input = i_stream_create_binary_converter(datainput); - for (i = 1; i <= sizeof(mail_input); i++) { + for (i = 1; i <= mail_input_len; i++) { test_istream_set_size(datainput, i); while ((ret = i_stream_read(input)) > 0) ; - test_assert(ret == 0); + test_assert_idx(ret == 0, idx); } test_istream_set_allow_eof(datainput, TRUE); while ((ret = i_stream_read(input)) > 0) ; - test_assert(ret == -1); + test_assert_idx(ret == -1, idx); data = i_stream_get_data(input, &size); - test_assert(size == sizeof(mail_output) && - memcmp(data, mail_output, size) == 0); + test_assert_idx(size == mail_output_len && + memcmp(data, mail_output, size) == 0, idx); i_stream_unref(&input); i_stream_unref(&datainput); +} + +static void test_istream_binary_converter_mime(void) +{ + test_begin("istream binary converter in mime parts"); + test_istream_binary_converter_test(mail_input_mime, sizeof(mail_input_mime)-1, + mail_output_mime, sizeof(mail_output_mime)-1, 0); + test_end(); +} + +static void test_istream_binary_converter_root(void) +{ + buffer_t *inbuf = buffer_create_dynamic(pool_datastack_create(), 512); + buffer_t *outbuf = buffer_create_dynamic(pool_datastack_create(), 512); + const char *const suffixes[] = { "\n", "\r\n", "\n\r\n\n\n" }; + unsigned int i; + unsigned int input_hdr_len = sizeof(mail_input_root_hdr)-1; + + test_begin("istream binary converter in root"); + buffer_append(inbuf, mail_input_root_hdr, input_hdr_len); + buffer_append(outbuf, mail_output_root_hdr, sizeof(mail_output_root_hdr)-1); + for (i = 0; i < N_ELEMENTS(suffixes); i++) { + buffer_set_used_size(inbuf, input_hdr_len); + buffer_set_used_size(outbuf, sizeof(mail_output_root_hdr)-1); + buffer_append(inbuf, BINARY_TEXT_SHORT, sizeof(BINARY_TEXT_SHORT)-1); + buffer_append(inbuf, suffixes[i], strlen(suffixes[i])); + base64_encode(CONST_PTR_OFFSET(inbuf->data, input_hdr_len), + inbuf->used - input_hdr_len, outbuf); + test_istream_binary_converter_test(inbuf->data, inbuf->used, + outbuf->data, outbuf->used, i); + } + test_end(); +} + +static void test_istream_binary_converter_root_nonbinary(void) +{ + test_begin("istream binary converter in root having non-binary"); + test_istream_binary_converter_test(mail_root_nonbinary, sizeof(mail_root_nonbinary)-1, + mail_root_nonbinary, sizeof(mail_root_nonbinary)-1, 0); test_end(); } @@ -142,7 +203,9 @@ int main(int argc, char *argv[]) { static void (*test_functions[])(void) = { - test_istream_binary_converter, + test_istream_binary_converter_mime, + test_istream_binary_converter_root, + test_istream_binary_converter_root_nonbinary, NULL }; if (argc > 1)