From 8a2f21f2b03878918333efac486f99e4fa0ecce2 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 6 Sep 2016 02:56:39 +0300 Subject: [PATCH] lib-dcrypt: Avoid infinite loop if istream header is too large. We'll return an error now instead. We can't just return -2 here, because nothing was actually being returned to the caller. Attempting to do that would just trigger an assert: Panic: file istream.c: line 182 (i_stream_read): assertion failed: (_stream->skip != _stream->pos) --- src/lib-dcrypt/istream-decrypt.c | 6 ++++++ src/lib-dcrypt/test-stream.c | 17 +++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/lib-dcrypt/istream-decrypt.c b/src/lib-dcrypt/istream-decrypt.c index 4f3ca12dfc..9da17e8a68 100644 --- a/src/lib-dcrypt/istream-decrypt.c +++ b/src/lib-dcrypt/istream-decrypt.c @@ -732,6 +732,12 @@ i_stream_decrypt_read(struct istream_private *stream) if (hret == 0) { /* see if we can get more data */ + if (ret == -2) { + stream->istream.stream_errno = EINVAL; + io_stream_set_error(&stream->iostream, + "Header too large (more than %"PRIuSIZE_T" bytes)", size); + return -1; + } continue; } else { /* clean up buffer */ diff --git a/src/lib-dcrypt/test-stream.c b/src/lib-dcrypt/test-stream.c index e62eed4784..aa5a7f48da 100644 --- a/src/lib-dcrypt/test-stream.c +++ b/src/lib-dcrypt/test-stream.c @@ -497,6 +497,22 @@ static void test_read_0_to_400_byte_garbage(void) test_end(); } +static void test_read_large_header(void) +{ + test_begin("test_read_large_header"); + + struct istream *is = test_istream_create_data(IOSTREAM_CRYPT_MAGIC, sizeof(IOSTREAM_CRYPT_MAGIC)); + struct istream *ds = i_stream_create_decrypt_callback(is, no_op_cb, NULL); + test_istream_set_allow_eof(is, FALSE); + test_istream_set_max_buffer_size(is, sizeof(IOSTREAM_CRYPT_MAGIC)); + + test_assert(i_stream_read(ds) == -1); + i_stream_unref(&ds); + i_stream_unref(&is); + + test_end(); +} + static void test_free_keys() { dcrypt_key_unref_private(&test_v1_kp.priv); @@ -529,6 +545,7 @@ int main(void) { test_write_read_v2_empty, test_free_keys, test_read_0_to_400_byte_garbage, + test_read_large_header, NULL };