Skip to content

Commit

Permalink
lib-mail: istream-binary-converter lost last few chars from root-leve…
Browse files Browse the repository at this point in the history
…l binary content.
  • Loading branch information
sirainen committed Jan 18, 2016
1 parent 498eecf commit 1e6170b
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 15 deletions.
11 changes: 9 additions & 2 deletions src/lib-mail/istream-binary-converter.c
Expand Up @@ -182,10 +182,19 @@ static ssize_t i_stream_binary_converter_read(struct istream_private *stream)

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;
Expand All @@ -196,8 +205,6 @@ static ssize_t i_stream_binary_converter_read(struct istream_private *stream)
break;
}

old_size = stream->pos - stream->skip;

if (block.part != bstream->convert_part &&
bstream->convert_part != NULL) {
/* end of base64 encoded part */
Expand Down
89 changes: 76 additions & 13 deletions src/lib-mail/test-istream-binary-converter.c
@@ -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"
Expand All @@ -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"
Expand All @@ -36,13 +38,13 @@ BINARY_TEXT_LONG
"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"
Expand All @@ -57,38 +59,97 @@ BINARY_TEXT_LONG_BASE64
"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();
}

Expand Down Expand Up @@ -142,7 +203,9 @@ static int test_input_file(const char *path)
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)
Expand Down

0 comments on commit 1e6170b

Please sign in to comment.